﻿// -------------------------------------------------------------------------
//    @FileName         :    NFIServerMessageModule.h
//    @Author           :    Gao.Yi
//    @Date             :   2022-09-18
//    @Email			:    445267987@qq.com
//    @Module           :    NFServerCommon
//    @Desc             :    服务器消息模块接口头文件，提供基于消息的通讯接口。
//                          该文件定义了服务器间高级消息通信的接口类，是NFFrame框架
//                          中处理分布式服务器通信的核心组件。提供了完整的服务器间
//                          消息传递、事务处理、数据库操作等高层次抽象接口。
//                          
//                          核心功能模块：
//                          - 服务器间消息通信管理（跨服务器类型的消息路由）
//                          - 分布式事务处理和状态管理
//                          - 数据库操作的高级封装（CRUD操作、条件查询）
//                          - RPC服务调用的便捷接口
//                          - 消息队列和异步处理管理
//                          - 智能负载均衡和故障转移支持
//                          - 协程化的数据库访问接口
//
// -------------------------------------------------------------------------

/**
 * @file NFIServerMessageModule.h
 * @brief 服务器消息模块接口定义
 * @details 该文件定义了NFrame框架中服务器间通信的高级接口，是构建分布式游戏服务器架构的关键组件：
 * 
 * **设计目标**：
 * - 提供类型安全的服务器间通信接口
 * - 简化分布式系统中的消息传递复杂性
 * - 统一数据库访问模式和事务处理
 * - 支持大规模分布式游戏服务器集群
 * 
 * **核心特性**：
 * - 基于服务器类型的智能路由
 * - 协程化的异步数据库操作
 * - 模板化的类型安全接口
 * - 内置的负载均衡和容错机制
 * - 支持批量操作和事务处理
 * 
 * **支持的服务器类型**：
 * - Master Server: 集群管理和配置中心
 * - World Server: 全局状态和跨区域通信
 * - Game Server: 游戏逻辑和玩家状态
 * - Logic Server: 业务逻辑处理
 * - Proxy Server: 客户端接入和负载均衡
 * - Store Server: 数据存储和持久化
 * - Online Server: 在线状态管理
 * - SNS Server: 社交功能和关系管理
 * 
 * **使用场景**：
 * - 大型多人在线游戏（MMORPG）
 * - 实时战斗游戏服务器
 * - 社交游戏平台
 * - 分布式业务系统
 * 
 * @author Gao.Yi
 * @date 2022-09-18
 * @version 1.0
 * @see NFIMessageModule 底层消息通信接口
 * @see NFStoreProtoCommon 数据库操作工具类
 * @see NFICoroutineModule 协程支持模块
 */

#pragma once

#include "NFComm/NFCore/NFPlatform.h"
#include "NFComm/NFPluginModule/NFError.h"
#include "NFComm/NFCore/NFPlatform.h"
#include "NFComm/NFPluginModule/NFIModule.h"
#include "NFComm/NFPluginModule/NFIDynamicModule.h"
#include "NFComm/NFPluginModule/NFStoreProtoCommon.h"
#include "NFServerBindRpcService.h"
#include "NFComm/NFPluginModule/NFProtobufCommon.h"
#include "NFComm/NFPluginModule/NFIMessageModule.h"
#include <map>
#include <unordered_map>
#include <list>
#include <string>
#include <map>
#include <functional>
#include <unordered_set>

//#define TEST_SERVER_SEND_MSG
#define TEST_SERVER_SEND_MSG_FRAME_COUNT 1

/**
 * @brief 基于消息的通讯接口类
 * 
 * 该类是服务器消息模块的核心接口，提供了：
 * - 服务器间消息通信功能
 * - 跨服务器消息路由
 * - 事务处理和状态管理
 * - 数据库操作接口
 * - RPC服务调用
 * - 消息队列管理
 * - 负载均衡支持
 * 
 * 支持多种服务器类型：
 * - Master Server (主服务器)
 * - World Server (世界服务器)
 * - Game Server (游戏服务器)
 * - Logic Server (逻辑服务器)
 * - Proxy Server (代理服务器)
 * - Store Server (存储服务器)
 * - Online Server (在线服务器)
 * - SNS Server (社交服务器)
 * 
 * 使用方式：
 * @code
 * // 发送消息到主服务器
 * pServerMessageModule->SendMsgToMasterServer(NF_ST_GAME_SERVER, msgId, data);
 * 
 * // 发送事务到存储服务器
 * pServerMessageModule->SendTransToStoreServer(NF_ST_GAME_SERVER, busId, cmd, tableId, dbname, tableName, data);
 * @endcode
 */
class NFIServerMessageModule : public NFIDynamicModule
{
public:
    /**
     * @brief 构造函数
     * @param p 插件管理器指针
     */
    NFIServerMessageModule(NFIPluginManager* p) : NFIDynamicModule(p)
    {
    }

    /**
     * @brief 析构函数
     */
    virtual ~NFIServerMessageModule()
    {
    }

public:
    /**
     * @brief 发送消息到主服务器
     * @param eSendTyp 发送方服务器类型，标识消息来源
     * @param nMsgId 消息ID，唯一标识消息类型和处理方式
     * @param xData Protobuf消息对象，包含具体的消息内容
     * @param nParam1 自定义参数1，用于传递额外的上下文信息，默认为0
     * @param nParam2 自定义参数2，用于传递额外的上下文信息，默认为0
     * @return 发送结果：0表示成功，非0值表示具体的错误码
     *
     * @details 向集群中的主服务器发送消息，主服务器负责集群管理和配置分发：
     * 
     * **主服务器功能**：
     * - 集群配置管理和分发
     * - 服务器注册和心跳监控
     * - 全局状态同步和协调
     * - 负载均衡策略管理
     * - 系统监控和告警
     * 
     * **消息路由机制**：
     * - 自动选择可用的主服务器实例
     * - 支持主服务器的高可用和故障转移
     * - 消息优先级和QoS保证
     * - 自动重试和超时处理
     * 
     * **使用场景**：
     * - 服务器状态报告和心跳
     * - 配置更新请求
     * - 集群事件通知
     * - 系统指标上报
     * 
     * @note 使用默认模块ID（NF_MODULE_SERVER）
     * @note 主服务器通常为集群中的单例服务
     * @see SendMsgToMasterServer 带模块ID的版本
     */
    virtual int SendMsgToMasterServer(NF_SERVER_TYPE eSendTyp, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送消息到主服务器（带模块ID）
     * @param eSendTyp 发送方服务器类型，标识消息来源
     * @param nModuleId 目标模块ID，用于精确路由到主服务器的特定模块
     * @param nMsgId 消息ID，唯一标识消息类型和处理方式
     * @param xData Protobuf消息对象，包含具体的消息内容
     * @param nParam1 自定义参数1，用于传递额外的上下文信息，默认为0
     * @param nParam2 自定义参数2，用于传递额外的上下文信息，默认为0
     * @return 发送结果：0表示成功，非0值表示具体的错误码
     *
     * @details 向主服务器的指定模块发送消息，支持模块化的消息处理：
     * 
     * **模块化设计**：
     * - 主服务器内部按功能模块划分
     * - 消息可以精确路由到特定模块
     * - 支持模块间的解耦和独立处理
     * - 提高系统的可维护性和扩展性
     * 
     * **常见模块类型**：
     * - 配置管理模块：处理配置更新和查询
     * - 监控模块：处理性能指标和告警
     * - 用户管理模块：处理账户和权限相关
     * - 日志模块：处理日志收集和分析
     * 
     * @note 模块ID必须与主服务器的实际模块配置匹配
     * @note 支持动态模块注册和卸载
     */
    virtual int SendMsgToMasterServer(NF_SERVER_TYPE eSendTyp, uint32_t nModuleId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

public:
    ////////////////////////////send proxy msg to other serer//////////////////////////////////
    /**
     * @brief 通过Bus ID发送代理消息
     * @param eType 目标服务器类型（通常是代理服务器类型）
     * @param nDstId 目标服务器的Bus ID，用于精确定位服务器实例
     * @param nMsgId 消息ID，标识消息类型和处理方式
     * @param xData Protobuf消息对象，包含要代理转发的消息内容
     * @param nParam1 自定义参数1，用于代理路由控制，默认为0
     * @param nParam2 自定义参数2，用于代理路由控制，默认为0
     * @return 发送结果：0表示成功，非0值表示具体的错误码
     *
     * @details 向指定的代理服务器发送需要代理转发的消息：
     * 
     * **代理服务器架构**：
     * - 作为客户端和后端服务器之间的中介
     * - 负责消息路由、负载均衡和连接管理
     * - 提供统一的客户端接入点
     * - 支持跨区域和跨网络的通信
     * 
     * **消息代理机制**：
     * - 消息透明转发，保持原始消息结构
     * - 支持消息的编解码和协议转换
     * - 提供消息缓存和重传机制
     * - 支持消息的分片和组装
     * 
     * **使用场景**：
     * - 客户端消息转发到后端服务器
     * - 跨区域服务器间的消息代理
     * - 负载均衡和故障转移
     * - 网络隔离环境下的消息中继
     * 
     * @note 使用默认模块ID进行消息路由
     * @note Bus ID必须对应实际存在的代理服务器实例
     * @see SendProxyMsgByBusId 带模块ID的版本
     */
    virtual int SendProxyMsgByBusId(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;
    virtual int SendProxyTransMsgByBusId(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nMsgId, const google::protobuf::Message& xData, uint32_t req_trans_id = 0, uint32_t rsp_trans_id = 0) = 0;

    /**
     * @brief 通过Bus ID发送代理消息（带模块ID）
     *
     * 向指定Bus ID的服务器发送代理消息，支持指定模块ID
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nModuleId 模块ID
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendProxyMsgByBusId(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nModuleId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 通过Bus ID发送代理消息（原始数据）
     *
     * 向指定Bus ID的服务器发送代理消息，支持原始数据格式
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nMsgId 消息ID
     * @param msg 消息数据指针
     * @param nLen 消息数据长度
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendProxyMsgByBusId(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nMsgId, const char* msg, uint32_t nLen, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 通过Bus ID发送代理消息（原始数据，带模块ID）
     *
     * 向指定Bus ID的服务器发送代理消息，支持原始数据格式和模块ID
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nModuleId 模块ID
     * @param nMsgId 消息ID
     * @param msg 消息数据指针
     * @param nLen 消息数据长度
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendProxyMsgByBusId(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nModuleId, uint32_t nMsgId, const char* msg, uint32_t nLen, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    ///////////////////////////other server send msg to proxy server/////////////////////////////
    /**
     * @brief 发送重定向消息到代理服务器
     *
     * 向指定的代理服务器发送重定向消息，支持指定多个客户端ID
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param ids 客户端ID集合
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @return 发送结果
     */
    virtual int SendRedirectMsgToProxyServer(NF_SERVER_TYPE eType, uint32_t nDstId, const std::unordered_set<uint64_t>& ids, uint32_t nMsgId, const google::protobuf::Message& xData) = 0;

    /**
     * @brief 发送重定向消息到所有代理服务器
     *
     * 向所有代理服务器发送重定向消息，支持指定多个客户端ID
     *
     * @param eType 目标服务器类型
     * @param ids 客户端ID集合
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @return 发送结果
     */
    virtual int SendRedirectMsgToAllProxyServer(NF_SERVER_TYPE eType, const std::unordered_set<uint64_t>& ids, uint32_t nMsgId, const google::protobuf::Message& xData) = 0;

    /**
     * @brief 发送重定向消息到所有代理服务器（无客户端ID）
     *
     * 向所有代理服务器发送重定向消息，不指定具体客户端ID
     *
     * @param eType 目标服务器类型
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @return 发送结果
     */
    virtual int SendRedirectMsgToAllProxyServer(NF_SERVER_TYPE eType, uint32_t nMsgId, const google::protobuf::Message& xData) = 0;

    /**
     * @brief 发送消息到代理服务器
     *
     * 向指定的代理服务器发送消息
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToProxyServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送消息到代理服务器（带模块ID）
     *
     * 向指定的代理服务器发送消息，支持指定模块ID
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nModuleId 模块ID
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToProxyServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nModuleId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送消息到代理服务器（字符串数据）
     *
     * 向指定的代理服务器发送消息，支持字符串数据格式
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nMsgId 消息ID
     * @param xData 消息数据字符串
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToProxyServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nMsgId, const std::string& xData, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送消息到代理服务器（字符串数据，带模块ID）
     *
     * 向指定的代理服务器发送消息，支持字符串数据格式和模块ID
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nModuleId 模块ID
     * @param nMsgId 消息ID
     * @param xData 消息数据字符串
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToProxyServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nModuleId, uint32_t nMsgId, const std::string& xData, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送消息到代理服务器（原始数据）
     *
     * 向指定的代理服务器发送消息，支持原始数据格式
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nMsgId 消息ID
     * @param pData 消息数据指针
     * @param dataLen 消息数据长度
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToProxyServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nMsgId, const char* pData, int dataLen, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送消息到代理服务器（原始数据，带模块ID）
     *
     * 向指定的代理服务器发送消息，支持原始数据格式和模块ID
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nModuleId 模块ID
     * @param nMsgId 消息ID
     * @param pData 消息数据指针
     * @param dataLen 消息数据长度
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToProxyServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nModuleId, uint32_t nMsgId, const char* pData, int dataLen, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    ///////////////////////////other server send msg to world server/////////////////////////////
    /**
     * @brief 发送消息到世界服务器
     *
     * 向世界服务器发送消息
     *
     * @param eType 目标服务器类型
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToWorldServer(NF_SERVER_TYPE eType, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送消息到世界服务器（带模块ID）
     *
     * 向世界服务器发送消息，支持指定模块ID
     *
     * @param eType 目标服务器类型
     * @param nModuleId 模块ID
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToWorldServer(NF_SERVER_TYPE eType, uint32_t nModuleId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送事务到世界服务器
     *
     * 向世界服务器发送事务消息
     *
     * @param eType 目标服务器类型
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param req_trans_id 请求事务ID，默认为0
     * @param rsp_trans_id
     * @return 发送结果
     */
    virtual int SendTransToWorldServer(NF_SERVER_TYPE eType, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint32_t req_trans_id = 0, uint32_t rsp_trans_id = 0) = 0;

    ///////////////////////////other server send msg to center server/////////////////////////////
    /**
     * @brief 发送消息到中心服务器
     *
     * 向中心服务器发送消息
     *
     * @param eType 目标服务器类型
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToCenterServer(NF_SERVER_TYPE eType, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送消息到中心服务器（带模块ID）
     *
     * 向中心服务器发送消息，支持指定模块ID
     *
     * @param eType 目标服务器类型
     * @param nModuleId 模块ID
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToCenterServer(NF_SERVER_TYPE eType, uint32_t nModuleId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送事务到中心服务器
     *
     * 向中心服务器发送事务消息
     *
     * @param eType 目标服务器类型
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param req_trans_id 请求事务ID，默认为0
     * @param rsp_trans_id
     * @return 发送结果
     */
    virtual int SendTransToCenterServer(NF_SERVER_TYPE eType, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey, uint32_t req_trans_id = 0, uint32_t rsp_trans_id = 0) = 0;

    ///////////////////////////other server send msg to game server/////////////////////////////
    /**
     * @brief 发送消息到游戏服务器
     *
     * 向指定的游戏服务器发送消息
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToGameServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送消息到游戏服务器（带模块ID）
     *
     * 向指定的游戏服务器发送消息，支持指定模块ID
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nModuleId 模块ID
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToGameServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nModuleId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送事务到游戏服务器
     *
     * 向指定的游戏服务器发送事务消息
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param req_trans_id 请求事务ID，默认为0
     * @return 发送结果
     */
    virtual int SendTransToGameServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint32_t req_trans_id = 0, uint32_t rsp_trans_id = 0) = 0;

    ///////////////////////////other server send msg to city server/////////////////////////////
    /**
     * @brief 发送消息到City服务器
     *
     * 向指定的City服务器发送消息
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToCityServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送消息到City服务器（带模块ID）
     *
     * 向指定的City服务器发送消息，支持指定模块ID
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nModuleId 模块ID
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToCityServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nModuleId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送事务到City服务器
     *
     * 向指定的City服务器发送事务消息
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param req_trans_id 请求事务ID，默认为0
     * @return 发送结果
     */
    virtual int SendTransToCityServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint32_t req_trans_id = 0, uint32_t rsp_trans_id = 0) = 0;
    ///////////////////////////other server send msg to logic server/////////////////////////////
    /**
     * @brief 发送消息到逻辑服务器
     *
     * 向指定的逻辑服务器发送消息
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToLogicServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送消息到逻辑服务器（带模块ID）
     *
     * 向指定的逻辑服务器发送消息，支持指定模块ID
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nModuleId 模块ID
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToLogicServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nModuleId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送事务到逻辑服务器
     *
     * 向指定的逻辑服务器发送事务消息
     *
     * @param eType 目标服务器类型
     * @param nDstId 目标Bus ID
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param req_trans_id 请求事务ID，默认为0
     * @return 发送结果
     */
    virtual int SendTransToLogicServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint32_t req_trans_id = 0, uint32_t rsp_trans_id = 0) = 0;
    ///////////////////////////other server send msg to sns server/////////////////////////////
    /**
     * @brief 发送消息到社交服务器
     *
     * 向社交服务器发送消息
     *
     * @param eType 目标服务器类型
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToSnsServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送消息到社交服务器（带模块ID）
     *
     * 向社交服务器发送消息，支持指定模块ID
     *
     * @param eType 目标服务器类型
     * @param nModuleId 模块ID
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToSnsServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nModuleId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送事务到社交服务器
     *
     * 向社交服务器发送事务消息
     *
     * @param eType 目标服务器类型
     * @param nDstId
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param req_trans_id 请求事务ID，默认为0
     * @return 发送结果
     */
    virtual int SendTransToSnsServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint32_t req_trans_id = 0, uint32_t rsp_trans_id = 0) = 0;
    ///////////////////////////other server send msg to online server/////////////////////////////
    /**
     * @brief 发送消息到在线服务器
     *
     * 向在线服务器发送消息
     *
     * @param eType 目标服务器类型
     * @param nDstId
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToOnlineServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送消息到在线服务器（带模块ID）
     *
     * 向在线服务器发送消息，支持指定模块ID
     *
     * @param eType 目标服务器类型
     * @param nDstId
     * @param nModuleId 模块ID
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param nParam1 参数1，默认为0
     * @param nParam2 参数2，默认为0
     * @return 发送结果
     */
    virtual int SendMsgToOnlineServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nModuleId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint64_t nParam1 = 0, uint64_t nParam2 = 0) = 0;

    /**
     * @brief 发送事务到在线服务器
     *
     * 向在线服务器发送事务消息
     *
     * @param eType 目标服务器类型
     * @param nDstId
     * @param nMsgId 消息ID
     * @param xData 消息数据
     * @param modKey
     * @param req_trans_id 请求事务ID，默认为0
     * @return 发送结果
     */
    virtual int SendTransToOnlineServer(NF_SERVER_TYPE eType, uint32_t nDstId, uint32_t nMsgId, const google::protobuf::Message& xData, uint64_t modKey = 0, uint32_t req_trans_id = 0, uint32_t rsp_trans_id = 0) = 0;

public:
    /**
     * @brief 发送事务到存储服务器
     * @param eType 发起事务的服务器类型，用于权限验证和日志记录
     * @param dstBusId 目标存储服务器的Bus ID，0表示自动选择
     * @param cmd 数据库操作命令（INSERT、UPDATE、DELETE、SELECT等）
     * @param table_id 表的唯一标识符，用于分片路由和权限控制
     * @param dbname 数据库名称，指定操作的目标数据库
     * @param table_name 表名称，指定操作的目标数据表
     * @param xData Protobuf消息对象，包含事务的具体数据
     * @param trans_id 事务ID，用于事务跟踪和回滚，默认为0（自动生成）
     * @param seq 操作序列号，用于保证操作顺序，默认为0
     * @param mod_key 分片键，用于数据分片和负载均衡，默认为0
     * @param cls_name 数据类名，用于类型验证和序列化，默认为空
     * @param packet_type 数据包类型，控制处理方式，默认为事务处理模式
     * @return 事务发送结果：0表示成功，非0值表示具体的错误码
     *
     * @details 向存储服务器发送数据库事务操作，支持ACID特性：
     * 
     * **事务特性**：
     * - **原子性（Atomicity）**：事务内的所有操作要么全部成功，要么全部失败
     * - **一致性（Consistency）**：事务执行前后数据库状态保持一致
     * - **隔离性（Isolation）**：并发事务之间相互隔离，不互相影响
     * - **持久性（Durability）**：事务提交后，数据持久保存到磁盘
     * 
     * **支持的操作类型**：
     * - INSERT：插入新记录，支持批量插入
     * - UPDATE：更新现有记录，支持条件更新
     * - DELETE：删除记录，支持条件删除
     * - SELECT：查询记录，支持复杂查询条件
     * - MERGE：合并操作（UPDATE或INSERT）
     * 
     * **分片和路由**：
     * - 基于mod_key进行数据分片
     * - 支持一致性哈希分布
     * - 自动选择最优的存储服务器
     * - 支持跨分片的分布式事务
     * 
     * **错误处理和恢复**：
     * - 自动重试机制，处理临时网络故障
     * - 事务回滚，保证数据一致性
     * - 死锁检测和解决
     * - 连接池管理，优化资源使用
     * 
     * **使用示例**：
     * @code
     * // 创建用户数据
     * UserInfo userInfo;
     * userInfo.set_user_id(12345);
     * userInfo.set_name("Alice");
     * userInfo.set_level(1);
     * 
     * // 发送插入事务
     * int ret = SendTransToStoreServer(
     *     NF_ST_GAME,           // 发起方服务器类型
     *     0,                    // 自动选择存储服务器
     *     NFrame::eST_INSERT,   // 插入操作
     *     1001,                 // 用户表ID
     *     "game_db",            // 数据库名
     *     "user_info",          // 表名
     *     userInfo,             // 数据对象
     *     0,                    // 自动生成事务ID
     *     0,                    // 序列号
     *     userInfo.user_id()    // 分片键
     * );
     * @endcode
     * 
     * @warning 确保数据库和表名的正确性，错误的名称会导致操作失败
     * @warning 大事务可能影响数据库性能，建议分批处理大量数据
     * @note 事务ID为0时系统会自动生成唯一ID
     * @note 支持跨表和跨库的复杂事务操作
     * @see GetRpcSelectObjService 查询单条记录的便捷方法
     * @see GetRpcInsertObjService 插入记录的便捷方法
     */
    virtual int SendTransToStoreServer(NF_SERVER_TYPE eType, uint32_t dstBusId, uint32_t cmd, uint32_t table_id, const std::string& dbname, const std::string& table_name, const google::protobuf::Message& xData, int trans_id = 0, uint32_t seq = 0, uint64_t mod_key = 0,
                                       const std::string& cls_name = "", uint8_t packet_type = NFrame::E_DISP_TYPE_BY_TRANSACTION) = 0;

    /**
     * @brief 发送事务到存储服务器（批量）
     *
     * 向存储服务器发送批量事务消息
     *
     * @param eType 目标服务器类型
     * @param dstBusId 目标Bus ID
     * @param cmd 命令
     * @param table_id 表ID
     * @param dbname 数据库名
     * @param table_name 表名
     * @param vecFileds 字段列表
     * @param vk_list 键值对列表
     * @param where_addtional_conds 附加条件
     * @param max_records 最大记录数，默认为100
     * @param trans_id 事务ID，默认为0
     * @param seq 序列号，默认为0
     * @param mod_key 模块键，默认为0
     * @param cls_name 类名
     * @param packet_type 数据包类型
     * @return 发送结果
     */
    virtual int SendTransToStoreServer(NF_SERVER_TYPE eType, uint32_t dstBusId, uint32_t cmd, uint32_t table_id, const std::string& dbname, const std::string& table_name, const std::vector<std::string>& vecFileds, const std::vector<NFrame::storesvr_vk>& vk_list,
                                       const std::string& where_addtional_conds, int max_records = 100, int trans_id = 0, uint32_t seq = 0, uint64_t mod_key = 0, const std::string& cls_name = "", uint8_t packet_type = NFrame::E_DISP_TYPE_BY_TRANSACTION) = 0;

    /**
     * @brief 发送事务到存储服务器（单条）
     *
     * 向存储服务器发送单条事务消息
     *
     * @param eType 目标服务器类型
     * @param dstBusId 目标Bus ID
     * @param cmd 命令
     * @param table_id 表ID
     * @param dbname 数据库名
     * @param table_name 表名
     * @param xData 消息数据
     * @param vk_list 键值对列表
     * @param where_addtional_conds 附加条件
     * @param trans_id 事务ID，默认为0
     * @param seq 序列号，默认为0
     * @param mod_key 模块键，默认为0
     * @param cls_name 类名
     * @param packet_type 数据包类型
     * @return 发送结果
     */
    virtual int SendTransToStoreServer(NF_SERVER_TYPE eType, uint32_t dstBusId, uint32_t cmd, uint32_t table_id, const std::string& dbname, const std::string& table_name, const google::protobuf::Message& xData, const std::vector<NFrame::storesvr_vk>& vk_list,
                                       const std::string& where_addtional_conds, int trans_id = 0, uint32_t seq = 0, uint64_t mod_key = 0, const std::string& cls_name = "", uint8_t packet_type = NFrame::E_DISP_TYPE_BY_TRANSACTION) = 0;

    /**
     * @brief 发送事务到存储服务器（字符串）
     *
     * 向存储服务器发送字符串事务消息
     *
     * @param eType 目标服务器类型
     * @param dstBusId 目标Bus ID
     * @param cmd 命令
     * @param table_id 表ID
     * @param dbname 数据库名
     * @param table_name 表名
     * @param xData 消息数据字符串
     * @param max_records 最大记录数，默认为100
     * @param trans_id 事务ID，默认为0
     * @param seq 序列号，默认为0
     * @param mod_key 模块键，默认为0
     * @param cls_name 类名
     * @param packet_type 数据包类型
     * @return 发送结果
     */
    virtual int SendTransToStoreServer(NF_SERVER_TYPE eType, uint32_t dstBusId, uint32_t cmd, uint32_t table_id, const std::string& dbname, const std::string& table_name, const std::string& xData, int max_records, int trans_id = 0, uint32_t seq = 0, uint64_t mod_key = 0,
                                       const std::string& cls_name = "", uint8_t packet_type = NFrame::E_DISP_TYPE_BY_TRANSACTION) = 0;

    /**
     * @brief 发送事务到存储服务器（单条，无事务）
     *
     * 向存储服务器发送单条事务消息，不包含事务ID
     *
     * @param eType 目标服务器类型
     * @param dstBusId 目标Bus ID
     * @param cmd 命令
     * @param table_id 表ID
     * @param dbname 数据库名
     * @param table_name 表名
     * @param xData 消息数据
     * @param trans_id 事务ID，默认为0
     * @param seq 序列号，默认为0
     * @param mod_key 模块键，默认为0
     * @param cls_name 类名
     * @param packet_type 数据包类型
     * @return 发送结果
     */
    virtual int SendTransToStoreServer(NF_SERVER_TYPE eType, uint32_t dstBusId, uint32_t cmd, uint32_t table_id, const std::string& dbname, const std::string& table_name, const std::string& xData, int trans_id = 0, uint32_t seq = 0, uint64_t mod_key = 0, const std::string& cls_name = "",
                                       uint8_t packet_type = NFrame::E_DISP_TYPE_BY_TRANSACTION) = 0;

public:
    ///////////////////////store server select obj////////////////////////////////////////////////////////////////////////
    /**
     * @brief 查询数据库中的单条记录（协程版本）
     * @tparam DataType 数据表对应的Protobuf结构体类型，必须包含主键字段
     * @param eType 发起查询的服务器类型，用于路由和权限验证
     * @param mod_key 哈希一致性键值，用于数据库分片路由，0表示随机选择
     * @param data 输入/输出参数：输入时包含查询的主键，输出时包含完整记录
     * @param vecFields 要查询的字段列表，为空时查询所有字段（减少网络传输）
     * @param dstBusId 目标存储服务器Bus ID，0表示自动选择
     * @param tbname 表名，为空时使用DataType的类名
     * @param dbname 数据库名，为空时使用默认数据库
     * @return 查询结果：0成功，其他值表示错误码
     * 
     * @details 这是一个协程化的同步数据库查询接口，具有以下特点：
     * 
     * **查询流程**：
     * 1. **参数验证**：验证数据库名和表名的有效性
     * 2. **服务器选择**：根据mod_key选择合适的存储服务器
     * 3. **请求构建**：构建selectobj请求，包含查询条件和字段列表
     * 4. **RPC调用**：通过RPC调用存储服务器的查询接口
     * 5. **结果解析**：将查询结果反序列化到data对象中
     * 
     * **性能优化**：
     * - 支持字段级查询，减少网络传输量
     * - 基于哈希一致性的分片路由
     * - 协程异步处理，不阻塞线程
     * - 智能服务器选择，支持负载均衡
     * 
     * **错误处理**：
     * - 网络错误：自动重试和故障转移
     * - 数据不存在：返回特定错误码 ERR_CODE_STORESVR_ERRCODE_SELECT_EMPTY
     * - 类型不匹配：编译时和运行时双重检查
     * 
     * **使用示例**：
     * @code
     * // 定义数据结构
     * UserInfo userInfo;
     * userInfo.set_user_id(12345);  // 设置查询条件
     * 
     * // 执行查询（必须在协程内）
     * int ret = GetRpcSelectObjService(NF_ST_GAME, userInfo.user_id(), userInfo);
     * if (ret == 0) {
     *     // 查询成功，userInfo现在包含完整数据
     *     std::string name = userInfo.name();
     *     int level = userInfo.level();
     * } else if (ret == NFrame::ERR_CODE_STORESVR_ERRCODE_SELECT_EMPTY) {
     *     // 记录不存在
     * } else {
     *     // 其他错误
     * }
     * @endcode
     * 
     * @warning 必须在协程上下文中调用，否则会阻塞当前线程
     * @warning data参数既是输入也是输出，调用前必须设置主键字段
     * @note 该方法是线程安全的，支持并发调用
     * @note 支持数据库连接池和读写分离
     * @see GetRpcSelectObjService 异步回调版本
     * @see GetRpcSelectService 批量查询版本
     */
    template <typename DataType>
    int GetRpcSelectObjService(NF_SERVER_TYPE eType, uint64_t mod_key, DataType& data, const std::vector<std::string>& vecFields = std::vector<std::string>(), uint32_t dstBusId = 0, const std::string& tbname = "", const std::string& dbname = "")
    {
        std::string tempDBName = dbname;
        if (dbname.empty())
        {
            NFServerConfig* pConfig = FindModule<NFIConfigModule>()->GetAppConfig(eType);
            if (pConfig)
            {
                tempDBName = pConfig->DefaultDBName;
            }
        }
        CHECK_EXPR(!tempDBName.empty(), -1, "no dbname ........");

        if (dstBusId == 0)
        {
            auto pDbServer = FindModule<NFIMessageModule>()->GetSuitDbServer(eType, tempDBName, mod_key);
            if (pDbServer)
            {
                dstBusId = pDbServer->mServerInfo.bus_id();
            }
        }

        NFrame::storesvr_selobj selobj;
        std::string clsname = NFProtobufCommon::GetProtoBaseName(data);
        std::string packageName = NFProtobufCommon::GetProtoPackageName(data);
        std::string tempTbName;
        if (tbname.empty())
        {
            tempTbName = clsname;
        }
        else
        {
            tempTbName = tbname;
        }

        CHECK_EXPR(!tempTbName.empty(), -1, "no tbname ........");
        NFStoreProtoCommon::storesvr_selectobj(selobj, tempDBName, tempTbName, mod_key, data, clsname, packageName, vecFields);

        NFrame::storesvr_selobj_res selobjRes;
        int iRet = FindModule<NFIMessageModule>()->GetRpcService<NF_MODULE_FRAME, NFrame::NF_STORESVR_C2S_SELECTOBJ>(eType, NF_ST_STORE_SERVER, dstBusId, selobj, selobjRes);
        auto& opres = selobjRes.opres();
        if (iRet == 0 && opres.err_code() == 0)
        {
            data.ParsePartialFromString(selobjRes.record());
        }
        else
        {
            if (iRet == 0)
            {
                iRet = opres.err_code();
                if (iRet != NFrame::ERR_CODE_STORESVR_ERRCODE_SELECT_EMPTY)
                {
                    NFLogError(NF_LOG_DEFAULT, 0, "NFrame::E_STORESVR_C2S_SELECTOBJ Failed, iRet:{} errMsg:{}", GetErrorStr(iRet), opres.errmsg());
                }
            }
            else
            {
                NFLogError(NF_LOG_DEFAULT, 0, "GetRpcService Failed, iRet:{}", GetErrorStr(iRet));
            }
        }
        return iRet;
    }

    /**
     * @brief 获取RPC选择对象服务（回调版本）
     *
     * 通过RPC调用向存储服务器查询对象数据，支持回调函数
     *
     * @tparam DataType 数据类型模板参数
     * @tparam ResponFunc 响应函数类型模板参数
     * @param eType 目标服务器类型
     * @param mod_key 模块键，用于哈希一致性
     * @param data 数据对象，用于存储查询结果
     * @param func 回调函数，用于处理操作结果
     * @param vecFields 要查询的字段列表，默认为空（查询所有字段）
     * @param dstBusId 目标Bus ID，默认为0（自动选择）
     * @param tbname 表名，默认为空（使用默认表名）
     * @param dbname 数据库名，默认为空（使用默认数据库）
     * @return 协程ID
     */
    template <class DataType, typename ResponFunc>
    int64_t GetRpcSelectObjService(NF_SERVER_TYPE eType, uint64_t mod_key, DataType& data, const ResponFunc& func, const std::vector<std::string>& vecFields = std::vector<std::string>(), uint32_t dstBusId = 0, const std::string& tbname = "", const std::string& dbname = "")
    {
        return GetRpcSelectObjServiceInner(eType, mod_key, data, func, &ResponFunc::operator(), vecFields, dstBusId, tbname, dbname);
    }

    /**
     * @brief 发送选择对象事务
     *
     * 向存储服务器发送选择对象事务消息
     *
     * @param eType 目标服务器类型
     * @param mod_key 模块键
     * @param data 数据对象
     * @param table_id 表ID，默认为0
     * @param trans_id 事务ID，默认为0
     * @param seq 序列号，默认为0
     * @param vecFields 字段列表，默认为空
     * @param dstBusId 目标Bus ID，默认为0
     * @param dbname 数据库名
     * @return
     */
    virtual int SendSelectObjTrans(NF_SERVER_TYPE eType, uint64_t mod_key, const google::protobuf::Message& data, uint32_t table_id = 0, int trans_id = 0, uint32_t seq = 0, const std::vector<std::string>& vecFields = std::vector<std::string>(), uint32_t dstBusId = 0,
                                   const std::string& dbname = "") = 0;

private:
    template <class DataType, typename ResponFunc>
    int64_t GetRpcSelectObjServiceInner(NF_SERVER_TYPE eType, uint64_t mod_key, DataType& data, const ResponFunc& responFunc, void (ResponFunc::*pf)(int rpcRetCode, DataType& respone) const, const std::vector<std::string>& vecFields = std::vector<std::string>(), uint32_t dstBusId = 0,
                                        const std::string& tbname = "", const std::string& dbname = "")
    {
        int64_t iRet = FindModule<NFICoroutineModule>()->MakeCoroutine([=, &data]()
        {
            DataType* pRespone = data.New();
            pRespone->CopyFrom(data);
            int rpcRetCode = GetRpcSelectObjService(eType, mod_key, *pRespone, vecFields, dstBusId, tbname, dbname);
            (responFunc.*pf)(rpcRetCode, *pRespone);
            NF_SAFE_DELETE(pRespone);
        });
        return iRet;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public:
    ///////////////////////store server select////////////////////////////////////////////////////////////////////////////
    /**
     * @brief 获取RPC描述存储服务
     *
     * 通过RPC调用获取描述存储服务的数据，支持字段过滤和条件查询
     *
     * @param eType 目标服务器类型
     * @param mod_key 模块键，用于哈希一致性
     * @param pDescStoreMessage 描述存储消息指针，用于存储查询结果
     * @param vecFields 要查询的字段列表，默认为空（查询所有字段）
     * @param where_addtional_conds 附加查询条件，默认为空
     * @param max_records 最大记录数，默认为100
     * @param dstBusId 目标Bus ID，默认为0（自动选择）
     * @param dbname 数据库名，默认为空（使用默认数据库）
     * @return 操作结果，0表示成功
     */
    int GetRpcDescStoreService(NF_SERVER_TYPE eType, uint64_t mod_key, google::protobuf::Message* pDescStoreMessage, const std::vector<std::string>& vecFields = std::vector<std::string>(), const std::string& where_addtional_conds = "", int max_records = 100, uint32_t dstBusId = 0,
                               const std::string& dbname = "")
    {
        std::string tempDBName = dbname;
        if (dbname.empty())
        {
            NFServerConfig* pConfig = FindModule<NFIConfigModule>()->GetAppConfig(eType);
            if (pConfig)
            {
                tempDBName = pConfig->DefaultDBName;
            }
        }
        CHECK_EXPR(!tempDBName.empty(), -1, "no dbname ........");

        if (dstBusId == 0)
        {
            auto pDbServer = FindModule<NFIMessageModule>()->GetSuitDbServer(eType, tempDBName, mod_key);
            if (pDbServer)
            {
                dstBusId = pDbServer->mServerInfo.bus_id();
            }
        }

        NFrame::storesvr_sel sel;
        std::string tbname = NFProtobufCommon::GetDescStoreClsName(*pDescStoreMessage);
        std::string packageName = NFProtobufCommon::GetProtoPackageName(*pDescStoreMessage);
        CHECK_EXPR(!tbname.empty(), -1, "no tbname ........");

        std::vector<NFrame::storesvr_vk> vk_list;
        NFStoreProtoCommon::storesvr_selectbycond(sel, tempDBName, tbname, mod_key, vecFields, vk_list, where_addtional_conds, max_records, tbname, packageName);

        NFrame::storesvr_sel_res selRes;
        STATIC_ASSERT_BIND_RPC_SERVICE(NFrame::NF_STORESVR_C2S_SELECT, NFrame::storesvr_sel, NFrame::storesvr_sel_res);
        NF_ASSERT_MSG(FindModule<NFICoroutineModule>()->IsInCoroutine(), "Call GetRpcService Must Int the Coroutine");
        NFServerConfig* pConfig = FindModule<NFIConfigModule>()->GetAppConfig(eType);
        CHECK_EXPR(pConfig, -1, "can't find server config! servertype:{}", GetServerName(eType));

        NFrame::Proto_FramePkg svrPkg;
        svrPkg.set_module_id(NF_MODULE_FRAME);
        svrPkg.set_msg_id(NFrame::NF_STORESVR_C2S_SELECT);
        svrPkg.set_msg_data(sel.SerializePartialAsString());
        auto pRpcInfo = svrPkg.mutable_rpc_info();
        pRpcInfo->set_req_rpc_id(FindModule<NFICoroutineModule>()->CurrentTaskId());
        pRpcInfo->set_req_rpc_hash(NFHash::hash<std::string>()(sel.GetTypeName()));
        pRpcInfo->set_rsp_rpc_hash(NFHash::hash<std::string>()(selRes.GetTypeName()));
        pRpcInfo->set_req_server_type(eType);
        pRpcInfo->set_req_bus_id(pConfig->BusId);

        FindModule<NFIMessageModule>()->SendMsgToServer(eType, NF_ST_STORE_SERVER, pConfig->BusId, dstBusId, NF_MODULE_FRAME, NFrame::NF_SERVER_TO_SERVER_RPC_CMD, svrPkg);

        int iRet = FindModule<NFICoroutineModule>()->SetUserData(&selRes);
        CHECK_EXPR(iRet == 0, iRet, "Yield Failed, Error:{}", GetErrorStr(iRet));

        do
        {
            iRet = FindModule<NFICoroutineModule>()->Yield(DEFINE_RPC_SERVICE_TIME_OUT_MS);
            CHECK_EXPR(iRet == 0, iRet, "Yield Failed, Error:{}", GetErrorStr(iRet));
            auto& opres = selRes.opres();
            if (iRet == 0 && opres.err_code() == 0)
            {
                const google::protobuf::Descriptor* pSheetFieldDesc = pDescStoreMessage->GetDescriptor();
                CHECK_EXPR(pSheetFieldDesc, -1, "pSheetFieldDesc == NULL");
                const google::protobuf::Reflection* pSheetReflect = pDescStoreMessage->GetReflection();
                CHECK_EXPR(pSheetReflect, -1, "pSheetFieldDesc == NULL");

                if (pSheetFieldDesc->field_count() > 0)
                {
                    /*  比如 message Sheet_GameRoomDesc
                    *		{
                    *			repeated GameRoomDesc GameRoomDesc_List = 1  [(nanopb).max_count=100];
                    *		}
                    *		获得上面GameRoomDesc_List信息
                    */
                    const google::protobuf::FieldDescriptor* pSheetRepeatedFieldDesc = pSheetFieldDesc->field(0);
                    if (pSheetRepeatedFieldDesc->is_repeated() && pSheetRepeatedFieldDesc->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)
                    {
                        //如果is_repeated 开始处理
                        for (int i = 0; i < (int)selRes.record_size(); i++)
                        {
                            ::google::protobuf::Message* pSheetRepeatedMessageObject = pSheetReflect->AddMessage(pDescStoreMessage, pSheetRepeatedFieldDesc);
                            pSheetRepeatedMessageObject->ParsePartialFromString(selRes.record(i));
                        }
                    }
                }

                if (selRes.is_lastbatch())
                {
                    break;
                }
            }
            else
            {
                if (iRet == 0)
                {
                    iRet = opres.err_code();
                    NFLogError(NF_LOG_DEFAULT, 0, "GetRpcDescStoreService Failed, iRet:{} errMsg:{}", GetErrorStr(iRet), opres.errmsg());
                }
                else
                {
                    NFLogError(NF_LOG_DEFAULT, 0, "GetRpcDescStoreService Failed, iRet:{}", GetErrorStr(iRet));
                }

                break;
            }
        }
        while (true);

        FindModule<NFICoroutineModule>()->SetUserData(NULL);

        return iRet;
    }

    /**
     * @brief 批量查询数据库记录（协程版本）
     * @tparam DataType 数据表对应的Protobuf结构体类型
     * @param eType 发起查询的服务器类型，用于路由和权限验证
     * @param mod_key 哈希一致性键值，用于数据库分片路由
     * @param data 数据类型模板对象，用于获取表名和包名（不包含查询条件）
     * @param respone 输出参数：存储查询结果的向量，每个元素代表一条记录
     * @param vecFields 要查询的字段列表，为空时查询所有字段
     * @param vk_list 键值对查询条件列表，支持多种操作符（=, >, <, >=, <=, !=, LIKE等）
     * @param where_addtional_conds 附加的SQL WHERE条件，支持复杂的逻辑表达式
     * @param max_records 单次查询的最大记录数，默认100，防止结果集过大
     * @param dstBusId 目标存储服务器Bus ID，0表示自动选择
     * @param dbname 数据库名，为空时使用默认数据库
     * @return 查询结果：0成功，其他值表示错误码
     * 
     * @details 这是一个功能强大的批量查询接口，支持复杂的查询条件：
     * 
     * **查询条件构建**：
     * - **字段选择**：vecFields指定需要的字段，减少网络传输
     * - **键值对条件**：vk_list支持结构化的查询条件
     * - **SQL条件**：where_addtional_conds支持原生SQL WHERE子句
     * - **结果限制**：max_records防止查询结果过大影响性能
     * 
     * **支持的查询类型**：
     * - 精确匹配：WHERE field = value
     * - 范围查询：WHERE field BETWEEN min AND max
     * - 模糊查询：WHERE field LIKE pattern
     * - 组合条件：AND、OR、NOT逻辑组合
     * - 排序查询：ORDER BY field ASC/DESC
     * 
     * **分批处理机制**：
     * - 大结果集自动分批返回，避免内存溢出
     * - 支持流式处理，实时处理每批数据
     * - 保持查询状态，确保数据一致性
     * 
     * **性能优化**：
     * - 智能索引选择，优化查询路径
     * - 查询计划缓存，加速重复查询
     * - 连接池复用，减少连接开销
     * - 结果集压缩，减少网络传输
     * 
     * **使用示例**：
     * @code
     * // 查询指定等级范围的用户
     * UserInfo userTemplate;  // 仅用于类型推导
     * std::vector<UserInfo> users;
     * 
     * // 构建查询条件
     * std::vector<NFrame::storesvr_vk> conditions;
     * conditions.push_back({"level", ">=", "10"});
     * conditions.push_back({"level", "<=", "20"});
     * 
     * // 只查询需要的字段
     * std::vector<std::string> fields = {"user_id", "name", "level"};
     * 
     * int ret = GetRpcSelectService(NF_ST_GAME, 0, userTemplate, users, 
     *                               fields, conditions, "", 1000);
     * if (ret == 0) {
     *     for (const auto& user : users) {
     *         NFLogInfo("用户: {} 等级: {}", user.name(), user.level());
     *     }
     * }
     * @endcode
     * 
     * @warning 必须在协程上下文中调用
     * @warning 大结果集查询可能消耗较多时间和内存
     * @note 支持分页查询，通过多次调用获取完整结果
     * @note 查询条件会自动进行SQL注入防护
     * @see GetRpcSelectObjService 单条记录查询
     * @see GetRpcDescStoreService 描述表查询
     */
    template <typename DataType>
    int GetRpcSelectService(NF_SERVER_TYPE eType, uint64_t mod_key, const DataType& data, std::vector<DataType>& respone, const std::vector<std::string>& vecFields = std::vector<std::string>(), const std::vector<NFrame::storesvr_vk>& vk_list = std::vector<NFrame::storesvr_vk>(),
                            const std::string& where_addtional_conds = "", int max_records = 100, uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        std::string tempDBName = dbname;
        if (dbname.empty())
        {
            NFServerConfig* pConfig = FindModule<NFIConfigModule>()->GetAppConfig(eType);
            if (pConfig)
            {
                tempDBName = pConfig->DefaultDBName;
            }
        }
        CHECK_EXPR(!tempDBName.empty(), -1, "no dbname ........");

        if (dstBusId == 0)
        {
            auto pDbServer = FindModule<NFIMessageModule>()->GetSuitDbServer(eType, tempDBName, mod_key);
            if (pDbServer)
            {
                dstBusId = pDbServer->mServerInfo.bus_id();
            }
        }

        NFrame::storesvr_sel sel;
        std::string tbname = NFProtobufCommon::GetProtoBaseName(data);
        std::string packageName = NFProtobufCommon::GetProtoPackageName(data);
        CHECK_EXPR(!tbname.empty(), -1, "no tbname ........");

        NFStoreProtoCommon::storesvr_selectbycond(sel, tempDBName, tbname, mod_key, vecFields, vk_list, where_addtional_conds, max_records, tbname, packageName);

        NFrame::storesvr_sel_res selRes;
        STATIC_ASSERT_BIND_RPC_SERVICE(NFrame::NF_STORESVR_C2S_SELECT, NFrame::storesvr_sel, NFrame::storesvr_sel_res);
        NF_ASSERT_MSG(FindModule<NFICoroutineModule>()->IsInCoroutine(), "Call GetRpcService Must Int the Coroutine");
        NFServerConfig* pConfig = FindModule<NFIConfigModule>()->GetAppConfig(eType);
        CHECK_EXPR(pConfig, -1, "can't find server config! servertype:{}", GetServerName(eType));

        NFrame::Proto_FramePkg svrPkg;
        svrPkg.set_module_id(NF_MODULE_FRAME);
        auto pRpcInfo = svrPkg.mutable_rpc_info();
        svrPkg.set_msg_id(NFrame::NF_STORESVR_C2S_SELECT);
        svrPkg.set_msg_data(sel.SerializePartialAsString());
        pRpcInfo->set_req_rpc_id(FindModule<NFICoroutineModule>()->CurrentTaskId());
        pRpcInfo->set_req_rpc_hash(NFHash::hash<std::string>()(sel.GetTypeName()));
        pRpcInfo->set_rsp_rpc_hash(NFHash::hash<std::string>()(selRes.GetTypeName()));
        pRpcInfo->set_req_server_type(eType);
        pRpcInfo->set_req_bus_id(pConfig->BusId);

        FindModule<NFIMessageModule>()->SendMsgToServer(eType, NF_ST_STORE_SERVER, pConfig->BusId, dstBusId, NF_MODULE_FRAME, NFrame::NF_SERVER_TO_SERVER_RPC_CMD, svrPkg);

        int iRet = FindModule<NFICoroutineModule>()->SetUserData(&selRes);
        CHECK_EXPR(iRet == 0, iRet, "Yield Failed, Error:{}", GetErrorStr(iRet));

        do
        {
            iRet = FindModule<NFICoroutineModule>()->Yield(DEFINE_RPC_SERVICE_TIME_OUT_MS);
            CHECK_EXPR(iRet == 0, iRet, "Yield Failed, Error:{}", GetErrorStr(iRet));
            auto& opres = selRes.opres();
            if (iRet == 0 && opres.err_code() == 0)
            {
                for (int i = 0; i < (int)selRes.record_size(); i++)
                {
                    DataType result;
                    result.ParsePartialFromString(selRes.record(i));
                    respone.push_back(result);
                }

                if (selRes.is_lastbatch())
                {
                    break;
                }
            }
            else
            {
                if (iRet == 0)
                {
                    iRet = opres.err_code();
                    NFLogError(NF_LOG_DEFAULT, 0, "NFrame::E_STORESVR_C2S_SELECT Failed, iRet:{} errMsg:{}", GetErrorStr(iRet), opres.errmsg());
                }
                else
                {
                    NFLogError(NF_LOG_DEFAULT, 0, "GetRpcService Failed, iRet:{}", GetErrorStr(iRet));
                }

                break;
            }
        }
        while (true);

        FindModule<NFICoroutineModule>()->SetUserData(NULL);

        return iRet;
    }

    /**
     * @brief 获取RPC选择服务（回调版本）
     *
     * 通过RPC调用向存储服务器查询数据，支持回调函数
     *
     * @tparam DataType 数据类型模板参数
     * @tparam ResponFunc 响应函数类型模板参数
     * @param eType 目标服务器类型
     * @param mod_key 模块键，用于哈希一致性
     * @param data 数据对象，用于获取表名和包名
     * @param func 回调函数，用于处理操作结果
     * @param vecFields 要查询的字段列表，默认为空（查询所有字段）
     * @param vk_list 键值对列表，用于条件查询，默认为空
     * @param where_addtional_conds 附加查询条件，默认为空
     * @param max_records 最大记录数，默认为100
     * @param dstBusId 目标Bus ID，默认为0（自动选择）
     * @param dbname 数据库名，默认为空（使用默认数据库）
     * @return 协程ID
     */
    template <class DataType, typename ResponFunc>
    int64_t GetRpcSelectService(NF_SERVER_TYPE eType, uint64_t mod_key, const DataType& data, const ResponFunc& func, const std::vector<std::string>& vecFields = std::vector<std::string>(), const std::vector<NFrame::storesvr_vk>& vk_list = std::vector<NFrame::storesvr_vk>(),
                                const std::string& where_addtional_conds = "", int max_records = 100, uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        return GetRpcSelectServiceInner(eType, mod_key, data, func, &ResponFunc::operator(), vecFields, vk_list, where_addtional_conds, max_records, dstBusId, dbname);
    }

    /**
     * @brief 发送选择事务
     *
     * 向存储服务器发送选择事务消息
     *
     * @param eType 目标服务器类型
     * @param mod_key 模块键
     * @param data 数据对象
     * @param table_id 表ID，默认为0
     * @param trans_id 事务ID，默认为0
     * @param seq 序列号，默认为0
     * @param vecFields 字段列表，默认为空
     * @param vk_list 键值对列表，默认为空
     * @param where_addtional_conds 附加条件，默认为空
     * @param max_records 最大记录数，默认为100
     * @param dstBusId 目标Bus ID，默认为0
     * @param dbname 数据库名
     * @return
     */
    virtual int SendSelectTrans(NF_SERVER_TYPE eType, uint64_t mod_key, const google::protobuf::Message& data, uint32_t table_id = 0, int trans_id = 0, const std::vector<std::string>& vecFields = std::vector<std::string>(),
                                const std::vector<NFrame::storesvr_vk>& vk_list = std::vector<NFrame::storesvr_vk>(), const std::string& where_addtional_conds = "", int max_records = 100, uint32_t dstBusId = 0, const std::string& dbname = "") = 0;

    /**
     * @brief 发送选择事务（带私钥）
     *
     * 向存储服务器发送选择事务消息，支持私钥
     *
     * @param eType 目标服务器类型
     * @param mod_key 模块键
     * @param data 数据对象
     * @param table_id 表ID，默认为0
     * @param trans_id 事务ID，默认为0
     * @param vecFields 字段列表，默认为空
     * @param privateKeys 私钥列表，默认为空
     * @param max_records 最大记录数，默认为100
     * @param dstBusId 目标Bus ID，默认为0
     * @param dbname 数据库名
     * @return
     */
    virtual int SendSelectTrans(NF_SERVER_TYPE eType, uint64_t mod_key, const google::protobuf::Message& data, uint32_t table_id = 0, int trans_id = 0, const std::vector<std::string>& vecFields = std::vector<std::string>(), const std::vector<std::string>& privateKeys = std::vector<std::string>(),
                                int max_records = 100, uint32_t dstBusId = 0, const std::string& dbname = "") = 0;

private:
    template <class DataType, typename ResponFunc>
    int64_t GetRpcSelectServiceInner(NF_SERVER_TYPE eType, uint64_t mod_key, const DataType& data, const ResponFunc& responFunc, void (ResponFunc::*pf)(int rpcRetCode, std::vector<DataType>& respone) const, const std::vector<std::string>& vecFields = std::vector<std::string>(),
                                     const std::vector<NFrame::storesvr_vk>& vk_list = std::vector<NFrame::storesvr_vk>(), const std::string& where_addtional_conds = "", int max_records = 100, uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        int64_t iRet = FindModule<NFICoroutineModule>()->MakeCoroutine([=]()
        {
            std::vector<DataType> respone;
            int rpcRetCode = GetRpcSelectService(eType, mod_key, data, respone, vecFields, vk_list, where_addtional_conds, max_records, dstBusId, dbname);

            (responFunc.*pf)(rpcRetCode, respone);
        });
        return iRet;
    }

public:
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////store server insert////////////////////////////////////////////////////////////////////////////
    /**
     * @brief 插入新记录到数据库（协程版本）
     * @tparam DataType 数据表对应的Protobuf结构体类型，必须包含完整的记录数据
     * @param eType 发起插入的服务器类型，用于路由和权限验证
     * @param mod_key 哈希一致性键值，用于数据库分片路由，通常使用主键值
     * @param data 要插入的完整数据对象，必须包含所有必需字段
     * @param dstBusId 目标存储服务器Bus ID，0表示自动选择
     * @param dbname 数据库名，为空时使用默认数据库
     * @return 插入结果：0成功，其他值表示错误码
     * 
     * @details 这是一个协程化的同步数据库插入接口，特点包括：
     * 
     * **插入流程**：
     * 1. **数据验证**：验证数据完整性和必需字段
     * 2. **分片路由**：根据mod_key选择目标数据库分片
     * 3. **服务器选择**：选择合适的存储服务器实例
     * 4. **请求构建**：构建insertobj请求包
     * 5. **RPC调用**：异步调用存储服务器的插入接口
     * 6. **结果处理**：处理插入结果和可能的约束冲突
     * 
     * **约束处理**：
     * - 主键冲突：自动检测和报告主键重复错误
     * - 外键约束：验证关联表的完整性
     * - 唯一索引：处理唯一约束冲突
     * - 数据类型：自动验证字段类型和长度
     * 
     * **性能特性**：
     * - 协程异步处理，高并发支持
     * - 批量插入优化（可配合事务使用）
     * - 智能分片，数据分布均匀
     * - 连接池复用，减少连接开销
     * 
     * **使用示例**：
     * @code
     * // 创建新用户记录
     * UserInfo newUser;
     * newUser.set_user_id(12345);
     * newUser.set_name("Alice");
     * newUser.set_level(1);
     * newUser.set_create_time(time(nullptr));
     * 
     * // 执行插入（必须在协程内）
     * int ret = GetRpcInsertObjService(NF_ST_GAME, newUser.user_id(), newUser);
     * if (ret == 0) {
     *     NFLogInfo("用户创建成功: {}", newUser.name());
     * } else {
     *     NFLogError("用户创建失败: {}", GetErrorStr(ret));
     * }
     * @endcode
     * 
     * @warning 必须在协程上下文中调用
     * @warning 确保data包含所有必需字段，否则可能导致插入失败
     * @note 支持自动生成的主键和时间戳字段
     * @note 插入成功后，自增字段会自动更新到data对象
     * @see GetRpcInsertObjService 异步回调版本
     * @see SendInsertObjTrans 事务版本
     */
    template <typename DataType>
    int GetRpcInsertObjService(NF_SERVER_TYPE eType, uint64_t mod_key, const DataType& data, uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        std::string tempDBName = dbname;
        if (dbname.empty())
        {
            NFServerConfig* pConfig = FindModule<NFIConfigModule>()->GetAppConfig(eType);
            if (pConfig)
            {
                tempDBName = pConfig->DefaultDBName;
            }
        }
        CHECK_EXPR(!tempDBName.empty(), -1, "no dbname ........");

        if (dstBusId == 0)
        {
            auto pDbServer = FindModule<NFIMessageModule>()->GetSuitDbServer(eType, tempDBName, mod_key);
            if (pDbServer)
            {
                dstBusId = pDbServer->mServerInfo.bus_id();
            }
        }

        NFrame::storesvr_insertobj selobj;
        std::string tbname = NFProtobufCommon::GetProtoBaseName(data);
        std::string packageName = NFProtobufCommon::GetProtoPackageName(data);
        CHECK_EXPR(!tbname.empty(), -1, "no tbname ........");
        NFStoreProtoCommon::storesvr_insertobj(selobj, tempDBName, tbname, mod_key, data, tbname, packageName);

        NFrame::storesvr_insertobj_res selobjRes;
        int iRet = FindModule<NFIMessageModule>()->GetRpcService<NF_MODULE_FRAME, NFrame::NF_STORESVR_C2S_INSERTOBJ>(eType, NF_ST_STORE_SERVER, dstBusId, selobj, selobjRes);
        auto& opres = selobjRes.opres();
        if (iRet == 0 && opres.err_code() == 0)
        {
            LOG_TRACE(0, "NFrame::NF_STORESVR_C2S_INSERTOBJ Success");
        }
        else
        {
            if (iRet == 0)
            {
                iRet = opres.err_code();
                NFLogError(NF_LOG_DEFAULT, 0, "NFrame::NF_STORESVR_C2S_INSERTOBJ Failed, iRet:{} errMsg:{}", GetErrorStr(iRet), opres.errmsg());
            }
            else
            {
                NFLogError(NF_LOG_DEFAULT, 0, "GetRpcService Failed, iRet:{}", GetErrorStr(iRet));
            }
        }
        return iRet;
    }

    /**
     * @brief 获取RPC插入对象服务（回调版本）
     *
     * 通过RPC调用向存储服务器插入对象数据，支持回调函数
     *
     * @tparam DataType 数据类型模板参数
     * @param eType 目标服务器类型
     * @param mod_key 模块键，用于哈希一致性
     * @param data 要插入的数据对象
     * @param func 回调函数，用于处理操作结果
     * @param dstBusId 目标Bus ID，默认为0（自动选择）
     * @param dbname 数据库名，默认为空（使用默认数据库）
     * @return 协程ID
     */
    template <class DataType>
    int64_t GetRpcInsertObjService(NF_SERVER_TYPE eType, uint64_t mod_key, const DataType& data, const std::function<void(int)>& func, uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        int64_t iRet = FindModule<NFICoroutineModule>()->MakeCoroutine([=, &data]()
        {
            int rpcRetCode = GetRpcInsertObjService(eType, mod_key, data, dstBusId, dbname);
            if (func)
            {
                func(rpcRetCode);
            }
        });
        return iRet;
    }

    /**
     * @brief 发送插入对象事务
     *
     * 向存储服务器发送插入对象事务消息
     *
     * @param eType 目标服务器类型
     * @param mod_key 模块键
     * @param data 数据对象
     * @param table_id 表ID，默认为0
     * @param trans_id 事务ID，默认为0
     * @param seq 序列号，默认为0
     * @param dstBusId 目标Bus ID，默认为0
     * @param dbname 数据库名
     * @return
     */
    virtual int SendInsertObjTrans(NF_SERVER_TYPE eType, uint64_t mod_key, const google::protobuf::Message& data, uint32_t table_id = 0, int trans_id = 0, uint32_t seq = 0, uint32_t dstBusId = 0, const std::string& dbname = "") = 0;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////store server modifyobj////////////////////////////////////////////////////////////////////////////
    /**
     * @brief 修改数据库对象（基于主键的协程版本）
     * @tparam DataType 数据表对应的Protobuf结构体类型
     * @param eType 发起修改的服务器类型，用于权限验证和日志记录
     * @param mod_key 哈希一致性键值，用于数据库分片路由，通常使用主键值
     * @param data 要修改的数据对象，必须包含主键和需要更新的字段
     * @param dstBusId 目标存储服务器Bus ID，0表示自动选择
     * @param dbname 数据库名，为空时使用默认数据库
     * @return 修改结果：0成功，其他值表示错误码
     * 
     * @details 这是一个协程化的数据库对象修改接口，特点包括：
     * 
     * **修改机制**：
     * - 基于主键的精确定位和修改
     * - 只更新data对象中已设置的字段
     * - 支持部分字段更新，不影响其他字段
     * - 自动处理数据类型转换和验证
     * 
     * **并发控制**：
     * - 乐观锁机制，避免数据冲突
     * - 版本号控制，检测并发修改
     * - 原子操作，保证修改的一致性
     * - 支持事务隔离级别配置
     * 
     * **性能优化**：
     * - 协程异步处理，高并发支持
     * - 智能分片路由，减少跨分片操作
     * - 索引优化，快速定位目标记录
     * - 批量修改支持，提高吞吐量
     * 
     * **使用示例**：
     * @code
     * // 修改用户等级
     * UserInfo userInfo;
     * userInfo.set_user_id(12345);     // 主键，必须设置
     * userInfo.set_level(25);          // 要修改的字段
     * userInfo.set_exp(8500);          // 要修改的字段
     * // 不设置name等其他字段，它们不会被修改
     * 
     * // 执行修改（必须在协程内）
     * int ret = GetRpcModifyObjService(NF_ST_GAME, userInfo.user_id(), userInfo);
     * if (ret == 0) {
     *     NFLogInfo("用户数据修改成功: {}", userInfo.user_id());
     * } else {
     *     NFLogError("用户数据修改失败: {}", GetErrorStr(ret));
     * }
     * @endcode
     * 
     * @warning 必须在协程上下文中调用
     * @warning data对象必须包含完整的主键信息
     * @warning 只有已设置的字段才会被更新到数据库
     * @note 如果记录不存在，操作会失败
     * @note 支持自动字段校验和约束检查
     * @see GetRpcModifyObjService 异步回调版本
     * @see GetRpcModifyService 条件修改版本
     */
    template <typename DataType>
    int GetRpcModifyObjService(NF_SERVER_TYPE eType, uint64_t mod_key, const DataType& data, uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        std::string tempDBName = dbname;
        if (dbname.empty())
        {
            NFServerConfig* pConfig = FindModule<NFIConfigModule>()->GetAppConfig(eType);
            if (pConfig)
            {
                tempDBName = pConfig->DefaultDBName;
            }
        }
        CHECK_EXPR(!tempDBName.empty(), -1, "no dbname ........");

        if (dstBusId == 0)
        {
            auto pDbServer = FindModule<NFIMessageModule>()->GetSuitDbServer(eType, tempDBName, mod_key);
            if (pDbServer)
            {
                dstBusId = pDbServer->mServerInfo.bus_id();
            }
        }

        NFrame::storesvr_modobj selobj;
        std::string tbname = NFProtobufCommon::GetProtoBaseName(data);
        std::string packageName = NFProtobufCommon::GetProtoPackageName(data);
        CHECK_EXPR(!tbname.empty(), -1, "no tbname ........");
        NFStoreProtoCommon::storesvr_modifyobj(selobj, tempDBName, tbname, mod_key, data, tbname, packageName);

        NFrame::storesvr_modobj_res selobjRes;
        int iRet = FindModule<NFIMessageModule>()->GetRpcService<NF_MODULE_FRAME, NFrame::NF_STORESVR_C2S_MODIFYOBJ>(eType, NF_ST_STORE_SERVER, dstBusId, selobj, selobjRes);
        auto& opres = selobjRes.opres();
        if (iRet == 0 && opres.err_code() == 0)
        {
            LOG_TRACE(0, "NFrame::NF_STORESVR_C2S_MODIFYOBJ Success");
        }
        else
        {
            if (iRet == 0)
            {
                iRet = opres.err_code();
                NFLogError(NF_LOG_DEFAULT, 0, "NFrame::NF_STORESVR_C2S_MODIFYOBJ Failed, iRet:{} errMsg:{}", GetErrorStr(iRet), opres.errmsg());
            }
            else
            {
                NFLogError(NF_LOG_DEFAULT, 0, "GetRpcService Failed, iRet:{}", GetErrorStr(iRet));
            }
        }
        return iRet;
    }

    /**
     * @brief 获取RPC修改对象服务（回调版本）
     *
     * 通过RPC调用向存储服务器修改对象数据，支持回调函数
     *
     * @tparam DataType 数据类型模板参数
     * @param eType 目标服务器类型
     * @param mod_key 模块键，用于哈希一致性
     * @param data 要修改的数据对象
     * @param func 回调函数，用于处理操作结果
     * @param dstBusId 目标Bus ID，默认为0（自动选择）
     * @param dbname 数据库名，默认为空（使用默认数据库）
     * @return 协程ID
     */
    template <class DataType>
    int64_t GetRpcModifyObjService(NF_SERVER_TYPE eType, uint64_t mod_key, const DataType& data, const std::function<void(int)>& func, uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        int64_t iRet = FindModule<NFICoroutineModule>()->MakeCoroutine([=, &data]()
        {
            int rpcRetCode = GetRpcModifyObjService(eType, mod_key, data, dstBusId, dbname);
            if (func)
            {
                func(rpcRetCode);
            }
        });
        return iRet;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////store server UpdateObj////////////////////////////////////////////////////////////////////////////
    /**
     * @brief 获取RPC更新对象服务（模板版本）
     *
     * 通过RPC调用向存储服务器更新对象数据
     *
     * @tparam DataType 数据类型模板参数
     * @param eType 目标服务器类型
     * @param mod_key 模块键，用于哈希一致性
     * @param data 要更新的数据对象
     * @param dstBusId 目标Bus ID，默认为0（自动选择）
     * @param dbname 数据库名，默认为空（使用默认数据库）
     * @return 操作结果，0表示成功
     */
    template <typename DataType>
    int GetRpcUpdateObjService(NF_SERVER_TYPE eType, uint64_t mod_key, const DataType& data, uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        std::string tempDBName = dbname;
        if (dbname.empty())
        {
            NFServerConfig* pConfig = FindModule<NFIConfigModule>()->GetAppConfig(eType);
            if (pConfig)
            {
                tempDBName = pConfig->DefaultDBName;
            }
        }
        CHECK_EXPR(!tempDBName.empty(), -1, "no dbname ........");

        if (dstBusId == 0)
        {
            auto pDbServer = FindModule<NFIMessageModule>()->GetSuitDbServer(eType, tempDBName, mod_key);
            if (pDbServer)
            {
                dstBusId = pDbServer->mServerInfo.bus_id();
            }
        }

        NFrame::storesvr_updateobj selobj;
        std::string tbname = NFProtobufCommon::GetProtoBaseName(data);
        std::string packageName = NFProtobufCommon::GetProtoPackageName(data);
        CHECK_EXPR(!tbname.empty(), -1, "no tbname ........");
        NFStoreProtoCommon::storesvr_updateobj(selobj, tempDBName, tbname, mod_key, data, tbname, packageName);

        NFrame::storesvr_updateobj_res selobjRes;
        int iRet = FindModule<NFIMessageModule>()->GetRpcService<NF_MODULE_FRAME, NFrame::NF_STORESVR_C2S_UPDATEOBJ>(eType, NF_ST_STORE_SERVER, dstBusId, selobj, selobjRes);
        auto& opres = selobjRes.opres();
        if (iRet == 0 && opres.err_code() == 0)
        {
            LOG_TRACE(0, "NFrame::NF_STORESVR_C2S_UPDATEOBJ Success");
        }
        else
        {
            if (iRet == 0)
            {
                iRet = opres.err_code();
                NFLogError(NF_LOG_DEFAULT, 0, "NFrame::NF_STORESVR_C2S_UPDATEOBJ Failed, iRet:{} errMsg:{}", GetErrorStr(iRet), opres.errmsg());
            }
            else
            {
                NFLogError(NF_LOG_DEFAULT, 0, "GetRpcService Failed, iRet:{}", GetErrorStr(iRet));
            }
        }
        return iRet;
    }

    /**
     * @brief 获取RPC更新对象服务（回调版本）
     *
     * 通过RPC调用向存储服务器更新对象数据，支持回调函数
     *
     * @tparam DataType 数据类型模板参数
     * @param eType 目标服务器类型
     * @param mod_key 模块键，用于哈希一致性
     * @param data 要更新的数据对象
     * @param func 回调函数，用于处理操作结果
     * @param dstBusId 目标Bus ID，默认为0（自动选择）
     * @param dbname 数据库名，默认为空（使用默认数据库）
     * @return 协程ID
     */
    template <class DataType>
    int64_t GetRpcUpdateObjService(NF_SERVER_TYPE eType, uint64_t mod_key, const DataType& data, const std::function<void(int)>& func, uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        int64_t iRet = FindModule<NFICoroutineModule>()->MakeCoroutine([=, &data]()
        {
            int rpcRetCode = GetRpcUpdateObjService(eType, mod_key, data, dstBusId, dbname);
            if (func)
            {
                func(rpcRetCode);
            }
        });
        return iRet;
    }

    /**
     * @brief 发送修改对象事务
     *
     * 向存储服务器发送修改对象事务消息
     *
     * @param eType 目标服务器类型
     * @param mod_key 模块键
     * @param data 数据对象
     * @param table_id 表ID，默认为0
     * @param trans_id 事务ID，默认为0
     * @param seq 序列号，默认为0
     * @param dstBusId 目标Bus ID，默认为0
     * @param dbname 数据库名
     * @return
     */
    virtual int SendModifyObjTrans(NF_SERVER_TYPE eType, uint64_t mod_key, const google::protobuf::Message& data, uint32_t table_id = 0, int trans_id = 0, uint32_t seq = 0, uint32_t dstBusId = 0, const std::string& dbname = "") = 0;
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////store server delete obj////////////////////////////////////////////////////////////////////////////
    /**
     * @brief 删除数据库对象（基于主键的协程版本）
     * @tparam DataType 数据表对应的Protobuf结构体类型
     * @param eType 发起删除的服务器类型，用于权限验证和审计日志
     * @param mod_key 哈希一致性键值，用于数据库分片路由，通常使用主键值
     * @param data 要删除的数据对象，只需包含主键信息
     * @param dstBusId 目标存储服务器Bus ID，0表示自动选择
     * @param dbname 数据库名，为空时使用默认数据库
     * @return 删除结果：0成功，其他值表示错误码
     * 
     * @details 这是一个协程化的数据库对象删除接口，特点包括：
     * 
     * **删除机制**：
     * - 基于主键的精确定位和删除
     * - 只需要提供主键信息，其他字段会被忽略
     * - 支持软删除和硬删除两种模式
     * - 自动处理关联数据的清理
     * 
     * **安全控制**：
     * - 权限验证，防止非法删除操作
     * - 审计日志，记录所有删除操作
     * - 确认机制，防止误删重要数据
     * - 备份策略，支持数据恢复
     * 
     * **事务保障**：
     * - 原子操作，要么删除成功要么完全回滚
     * - 外键约束检查，防止数据不一致
     * - 级联删除支持，自动处理关联数据
     * - 死锁检测和解决
     * 
     * **性能特性**：
     * - 协程异步处理，不阻塞其他操作
     * - 索引优化，快速定位目标记录
     * - 批量删除支持，提高删除效率
     * - 空间回收，自动释放已删除数据的存储空间
     * 
     * **使用示例**：
     * @code
     * // 删除指定用户
     * UserInfo userInfo;
     * userInfo.set_user_id(12345);     // 只需要设置主键
     * // 其他字段不需要设置，会被忽略
     * 
     * // 执行删除（必须在协程内）
     * int ret = GetRpcDeleteObjService(NF_ST_GAME, userInfo.user_id(), userInfo);
     * if (ret == 0) {
     *     NFLogInfo("用户删除成功: {}", userInfo.user_id());
     * } else if (ret == NFrame::ERR_CODE_STORESVR_ERRCODE_SELECT_EMPTY) {
     *     NFLogWarning("用户不存在: {}", userInfo.user_id());
     * } else {
     *     NFLogError("用户删除失败: {}", GetErrorStr(ret));
     * }
     * @endcode
     * 
     * @warning 必须在协程上下文中调用
     * @warning 删除操作不可逆，请谨慎使用
     * @warning data对象必须包含完整的主键信息
     * @note 如果记录不存在，会返回特定的错误码
     * @note 删除操作会触发相关的数据库触发器
     * @see GetRpcDeleteObjService 异步回调版本
     * @see GetRpcDeleteService 条件删除版本
     */
    template <typename DataType>
    int GetRpcDeleteObjService(NF_SERVER_TYPE eType, uint64_t mod_key, const DataType& data, uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        std::string tempDBName = dbname;
        if (dbname.empty())
        {
            NFServerConfig* pConfig = FindModule<NFIConfigModule>()->GetAppConfig(eType);
            if (pConfig)
            {
                tempDBName = pConfig->DefaultDBName;
            }
        }
        CHECK_EXPR(!tempDBName.empty(), -1, "no dbname ........");

        if (dstBusId == 0)
        {
            auto pDbServer = FindModule<NFIMessageModule>()->GetSuitDbServer(eType, tempDBName, mod_key);
            if (pDbServer)
            {
                dstBusId = pDbServer->mServerInfo.bus_id();
            }
        }

        NFrame::storesvr_delobj selobj;
        std::string tbname = NFProtobufCommon::GetProtoBaseName(data);
        std::string packageName = NFProtobufCommon::GetProtoPackageName(data);
        CHECK_EXPR(!tbname.empty(), -1, "no tbname ........");
        NFStoreProtoCommon::storesvr_deleteobj(selobj, tempDBName, tbname, mod_key, data, tbname, packageName);

        NFrame::storesvr_delobj_res selobjRes;
        int iRet = FindModule<NFIMessageModule>()->GetRpcService<NF_MODULE_FRAME, NFrame::NF_STORESVR_C2S_DELETEOBJ>(eType, NF_ST_STORE_SERVER, dstBusId, selobj, selobjRes);
        auto& opres = selobjRes.opres();
        if (iRet == 0 && opres.err_code() == 0)
        {
            LOG_TRACE(0, "NFrame::NF_STORESVR_C2S_DELETEOBJ Success");
        }
        else
        {
            if (iRet == 0)
            {
                iRet = opres.err_code();
                NFLogError(NF_LOG_DEFAULT, 0, "NFrame::NF_STORESVR_C2S_DELETEOBJ Failed, iRet:{} errMsg:{}", GetErrorStr(iRet), opres.errmsg());
            }
            else
            {
                NFLogError(NF_LOG_DEFAULT, 0, "GetRpcService Failed, iRet:{}", GetErrorStr(iRet));
            }
        }
        return iRet;
    }

    /**
     * @brief 获取RPC删除对象服务（回调版本）
     *
     * 通过RPC调用向存储服务器删除对象数据，支持回调函数
     *
     * @tparam DataType 数据类型模板参数
     * @param eType 目标服务器类型
     * @param mod_key 模块键，用于哈希一致性
     * @param data 要删除的数据对象
     * @param func 回调函数，用于处理操作结果
     * @param dstBusId 目标Bus ID，默认为0（自动选择）
     * @param dbname 数据库名，默认为空（使用默认数据库）
     * @return 协程ID
     */
    template <class DataType>
    int64_t GetRpcDeleteObjService(NF_SERVER_TYPE eType, uint64_t mod_key, const DataType& data, const std::function<void(int)>& func, uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        int64_t iRet = FindModule<NFICoroutineModule>()->MakeCoroutine([=, &data]()
        {
            int rpcRetCode = GetRpcDeleteObjService(eType, mod_key, data, dstBusId, dbname);
            if (func)
            {
                func(rpcRetCode);
            }
        });
        return iRet;
    }

    /**
     * @brief 发送删除对象事务
     *
     * 向存储服务器发送删除对象事务消息
     *
     * @param eType 目标服务器类型
     * @param mod_key 模块键
     * @param data 数据对象
     * @param table_id 表ID，默认为0
     * @param trans_id 事务ID，默认为0
     * @param seq 序列号，默认为0
     * @param dstBusId 目标Bus ID，默认为0
     * @param dbname 数据库名
     * @return
     */
    virtual int SendDeleteObjTrans(NF_SERVER_TYPE eType, uint64_t mod_key, const google::protobuf::Message& data, uint32_t table_id = 0, int trans_id = 0, uint32_t seq = 0, uint32_t dstBusId = 0, const std::string& dbname = "") = 0;
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////store server delete////////////////////////////////////////////////////////////////////////////
    /**
     * @brief 获取RPC删除服务（模板版本）
     *
     * 通过RPC调用向存储服务器删除数据，支持条件删除
     *
     * @tparam DataType 数据类型模板参数
     * @param eType 目标服务器类型
     * @param mod_key 模块键，用于哈希一致性
     * @param data 数据对象，用于获取表名和包名
     * @param vk_list 键值对列表，用于条件删除，默认为空
     * @param where_addtional_conds 附加删除条件，默认为空
     * @param dstBusId 目标Bus ID，默认为0（自动选择）
     * @param dbname 数据库名，默认为空（使用默认数据库）
     * @return 操作结果，0表示成功
     */
    template <typename DataType>
    int GetRpcDeleteService(NF_SERVER_TYPE eType, uint64_t mod_key, const DataType& data, const std::vector<NFrame::storesvr_vk>& vk_list = std::vector<NFrame::storesvr_vk>(), const std::string& where_addtional_conds = "", uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        std::string tempDBName = dbname;
        if (dbname.empty())
        {
            NFServerConfig* pConfig = FindModule<NFIConfigModule>()->GetAppConfig(eType);
            if (pConfig)
            {
                tempDBName = pConfig->DefaultDBName;
            }
        }
        CHECK_EXPR(!tempDBName.empty(), -1, "no dbname ........");

        if (dstBusId == 0)
        {
            auto pDbServer = FindModule<NFIMessageModule>()->GetSuitDbServer(eType, tempDBName, mod_key);
            if (pDbServer)
            {
                dstBusId = pDbServer->mServerInfo.bus_id();
            }
        }

        NFrame::storesvr_del selobj;
        std::string tbname = NFProtobufCommon::GetProtoBaseName(data);
        std::string packageName = NFProtobufCommon::GetProtoPackageName(data);
        CHECK_EXPR(!tbname.empty(), -1, "no tbname ........");
        NFStoreProtoCommon::storesvr_deletebycond(selobj, tempDBName, tbname, mod_key, vk_list, where_addtional_conds, tbname, packageName);

        NFrame::storesvr_del_res selobjRes;
        int iRet = FindModule<NFIMessageModule>()->GetRpcService<NF_MODULE_FRAME, NFrame::NF_STORESVR_C2S_DELETE>(eType, NF_ST_STORE_SERVER, dstBusId, selobj, selobjRes);
        auto& opres = selobjRes.opres();
        if (iRet == 0 && opres.err_code() == 0)
        {
            LOG_TRACE(0, "NFrame::NF_STORESVR_C2S_DELETE Success");
        }
        else
        {
            if (iRet == 0)
            {
                iRet = opres.err_code();
                NFLogError(NF_LOG_DEFAULT, 0, "NFrame::NF_STORESVR_C2S_DELETE Failed, iRet:{} errMsg:{}", GetErrorStr(iRet), opres.errmsg());
            }
            else
            {
                NFLogError(NF_LOG_DEFAULT, 0, "GetRpcService Failed, iRet:{}", GetErrorStr(iRet));
            }
        }
        return iRet;
    }

    /**
     * @brief 获取RPC删除服务（回调版本）
     *
     * 通过RPC调用向存储服务器删除数据，支持条件删除和回调函数
     *
     * @tparam DataType 数据类型模板参数
     * @param eType 目标服务器类型
     * @param mod_key 模块键，用于哈希一致性
     * @param data 数据对象，用于获取表名和包名
     * @param func 回调函数，用于处理操作结果
     * @param vk_list 键值对列表，用于条件删除，默认为空
     * @param where_addtional_conds 附加删除条件，默认为空
     * @param dstBusId 目标Bus ID，默认为0（自动选择）
     * @param dbname 数据库名，默认为空（使用默认数据库）
     * @return 协程ID
     */
    template <class DataType>
    int64_t GetRpcDeleteService(NF_SERVER_TYPE eType, uint64_t mod_key, const DataType& data, const std::function<void(int)>& func, const std::vector<NFrame::storesvr_vk>& vk_list = std::vector<NFrame::storesvr_vk>(), const std::string& where_addtional_conds = "", uint32_t dstBusId = 0,
                                const std::string& dbname = "")
    {
        int64_t iRet = FindModule<NFICoroutineModule>()->MakeCoroutine([=, &data]()
        {
            int rpcRetCode = GetRpcDeleteService(eType, mod_key, data, vk_list, where_addtional_conds, dstBusId, dbname);
            if (func)
            {
                func(rpcRetCode);
            }
        });
        return iRet;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////store server modify////////////////////////////////////////////////////////////////////////////
    /**
     * @brief 获取RPC修改服务（模板版本）
     *
     * 通过RPC调用向存储服务器修改数据，支持条件修改
     *
     * @tparam DataType 数据类型模板参数
     * @param eType 目标服务器类型
     * @param mod_key 模块键，用于哈希一致性
     * @param data 要修改的数据对象
     * @param vk_list 键值对列表，用于条件修改，默认为空
     * @param where_addtional_conds 附加修改条件，默认为空
     * @param dstBusId 目标Bus ID，默认为0（自动选择）
     * @param dbname 数据库名，默认为空（使用默认数据库）
     * @return 操作结果，0表示成功
     */
    template <typename DataType>
    int GetRpcModifyService(NF_SERVER_TYPE eType, uint64_t mod_key, const DataType& data, const std::vector<NFrame::storesvr_vk>& vk_list = std::vector<NFrame::storesvr_vk>(), const std::string& where_addtional_conds = "", uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        std::string tempDBName = dbname;
        if (dbname.empty())
        {
            NFServerConfig* pConfig = FindModule<NFIConfigModule>()->GetAppConfig(eType);
            if (pConfig)
            {
                tempDBName = pConfig->DefaultDBName;
            }
        }
        CHECK_EXPR(!tempDBName.empty(), -1, "no dbname ........");

        if (dstBusId == 0)
        {
            auto pDbServer = FindModule<NFIMessageModule>()->GetSuitDbServer(eType, tempDBName, mod_key);
            if (pDbServer)
            {
                dstBusId = pDbServer->mServerInfo.bus_id();
            }
        }

        NFrame::storesvr_mod selobj;
        std::string tbname = NFProtobufCommon::GetProtoBaseName(data);
        std::string packageName = NFProtobufCommon::GetProtoPackageName(data);
        CHECK_EXPR(!tbname.empty(), -1, "no tbname ........");
        NFStoreProtoCommon::storesvr_modifybycond(selobj, tempDBName, tbname, mod_key, data, vk_list, where_addtional_conds, tbname, packageName);

        NFrame::storesvr_mod_res selobjRes;
        int iRet = FindModule<NFIMessageModule>()->GetRpcService<NF_MODULE_FRAME, NFrame::NF_STORESVR_C2S_MODIFY>(eType, NF_ST_STORE_SERVER, dstBusId, selobj, selobjRes);
        auto& opres = selobjRes.opres();
        if (iRet == 0 && opres.err_code() == 0)
        {
            LOG_TRACE(0, "NFrame::NF_STORESVR_C2S_INSERTOBJ Success");
        }
        else
        {
            if (iRet == 0)
            {
                iRet = opres.err_code();
                NFLogError(NF_LOG_DEFAULT, 0, "NFrame::NF_STORESVR_C2S_MODIFY Failed, iRet:{} errMsg:{}", GetErrorStr(iRet), opres.errmsg());
            }
            else
            {
                NFLogError(NF_LOG_DEFAULT, 0, "GetRpcService Failed, iRet:{}", GetErrorStr(iRet));
            }
        }
        return iRet;
    }

    /**
     * @brief 获取RPC修改服务（回调版本）
     *
     * 通过RPC调用向存储服务器修改数据，支持条件修改和回调函数
     *
     * @tparam DataType 数据类型模板参数
     * @param eType 目标服务器类型
     * @param mod_key 模块键，用于哈希一致性
     * @param data 要修改的数据对象
     * @param func 回调函数，用于处理操作结果
     * @param vk_list 键值对列表，用于条件修改，默认为空
     * @param where_addtional_conds 附加修改条件，默认为空
     * @param dstBusId 目标Bus ID，默认为0（自动选择）
     * @param dbname 数据库名，默认为空（使用默认数据库）
     * @return 协程ID
     */
    template <class DataType>
    int64_t GetRpcModifyService(NF_SERVER_TYPE eType, uint64_t mod_key, const DataType& data, const std::function<void(int)>& func, const std::vector<NFrame::storesvr_vk>& vk_list = std::vector<NFrame::storesvr_vk>(), const std::string& where_addtional_conds = "", uint32_t dstBusId = 0,
                                const std::string& dbname = "")
    {
        int64_t iRet = FindModule<NFICoroutineModule>()->MakeCoroutine([=, &data]()
        {
            int rpcRetCode = GetRpcModifyService(eType, mod_key, data, vk_list, where_addtional_conds, dstBusId, dbname);
            if (func)
            {
                func(rpcRetCode);
            }
        });
        return iRet;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////store server select////////////////////////////////////////////////////////////////////////////
    /**
     * @brief 获取RPC更新服务（模板版本）
     *
     * 通过RPC调用向存储服务器更新数据，支持条件更新
     *
     * @tparam DataType 数据类型模板参数
     * @param eType 目标服务器类型
     * @param mod_key 模块键，用于哈希一致性
     * @param data 要更新的数据对象
     * @param vk_list 键值对列表，用于条件更新，默认为空
     * @param where_addtional_conds 附加更新条件，默认为空
     * @param dstBusId 目标Bus ID，默认为0（自动选择）
     * @param dbname 数据库名，默认为空（使用默认数据库）
     * @return 操作结果，0表示成功
     */
    template <typename DataType>
    int GetRpcUpdateService(NF_SERVER_TYPE eType, uint64_t mod_key, const DataType& data, const std::vector<NFrame::storesvr_vk>& vk_list = std::vector<NFrame::storesvr_vk>(), const std::string& where_addtional_conds = "", uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        std::string tempDBName = dbname;
        if (dbname.empty())
        {
            NFServerConfig* pConfig = FindModule<NFIConfigModule>()->GetAppConfig(eType);
            if (pConfig)
            {
                tempDBName = pConfig->DefaultDBName;
            }
        }
        CHECK_EXPR(!tempDBName.empty(), -1, "no dbname ........");

        if (dstBusId == 0)
        {
            auto pDbServer = FindModule<NFIMessageModule>()->GetSuitDbServer(eType, tempDBName, mod_key);
            if (pDbServer)
            {
                dstBusId = pDbServer->mServerInfo.bus_id();
            }
        }

        NFrame::storesvr_update selobj;
        std::string tbname = NFProtobufCommon::GetProtoBaseName(data);
        std::string packageName = NFProtobufCommon::GetProtoPackageName(data);
        CHECK_EXPR(!tbname.empty(), -1, "no tbname ........");
        NFStoreProtoCommon::storesvr_updatebycond(selobj, tempDBName, tbname, mod_key, data, vk_list, where_addtional_conds, tbname, packageName);

        NFrame::storesvr_update_res selobjRes;
        int iRet = FindModule<NFIMessageModule>()->GetRpcService<NF_MODULE_FRAME, NFrame::NF_STORESVR_C2S_UPDATE>(eType, NF_ST_STORE_SERVER, dstBusId, selobj, selobjRes);
        auto& opres = selobjRes.opres();
        if (iRet == 0 && opres.err_code() == 0)
        {
            LOG_TRACE(0, "NFrame::NF_STORESVR_C2S_MODINS Success");
        }
        else
        {
            if (iRet == 0)
            {
                iRet = opres.err_code();
                NFLogError(NF_LOG_DEFAULT, 0, "NFrame::NF_STORESVR_C2S_MODINS Failed, iRet:{} errMsg:{}", GetErrorStr(iRet), opres.errmsg());
            }
            else
            {
                NFLogError(NF_LOG_DEFAULT, 0, "GetRpcService Failed, iRet:{}", GetErrorStr(iRet));
            }
        }
        return iRet;
    }

    /**
     * @brief 获取RPC更新服务（回调版本）
     *
     * 通过RPC调用向存储服务器更新数据，支持条件更新和回调函数
     *
     * @tparam DataType 数据类型模板参数
     * @param eType 目标服务器类型
     * @param mod_key 模块键，用于哈希一致性
     * @param data 要更新的数据对象
     * @param func 回调函数，用于处理操作结果
     * @param vk_list 键值对列表，用于条件更新，默认为空
     * @param where_addtional_conds 附加更新条件，默认为空
     * @param dstBusId 目标Bus ID，默认为0（自动选择）
     * @param dbname 数据库名，默认为空（使用默认数据库）
     * @return 协程ID
     */
    template <class DataType>
    int64_t GetRpcUpdateService(NF_SERVER_TYPE eType, uint64_t mod_key, const DataType& data, const std::function<void(int)>& func, const std::vector<NFrame::storesvr_vk>& vk_list = std::vector<NFrame::storesvr_vk>(), const std::string& where_addtional_conds = "", uint32_t dstBusId = 0,
                                const std::string& dbname = "")
    {
        int64_t iRet = FindModule<NFICoroutineModule>()->MakeCoroutine([=, &data]()
        {
            int rpcRetCode = GetRpcUpdateService(eType, mod_key, data, vk_list, where_addtional_conds, dstBusId, dbname);
            if (func)
            {
                func(rpcRetCode);
            }
        });
        return iRet;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////store server update////////////////////////////////////////////////////////////////////////////
    /**
     * @brief 执行原生SQL语句（协程版本）
     * @tparam DataType 结果数据类型，用于接收SQL执行结果
     * @param eType 发起SQL执行的服务器类型，用于权限验证
     * @param mod_key 哈希一致性键值，用于选择数据库分片
     * @param data 数据对象，用于存储SQL执行的结果
     * @param sql 要执行的SQL语句，支持标准SQL语法
     * @param dstBusId 目标存储服务器Bus ID，0表示自动选择
     * @param dbname 数据库名，为空时使用默认数据库
     * @return 执行结果：0成功，其他值表示错误码
     * 
     * @details 这是一个协程化的原生SQL执行接口，提供强大的数据库操作能力：
     * 
     * **支持的SQL类型**：
     * - **查询语句**：SELECT，支持复杂的JOIN、子查询、聚合函数
     * - **数据操作**：INSERT、UPDATE、DELETE的复杂操作
     * - **数据定义**：CREATE、ALTER、DROP等结构操作
     * - **存储过程**：CALL存储过程调用
     * - **事务控制**：BEGIN、COMMIT、ROLLBACK等
     * 
     * **高级特性**：
     * - 参数化查询，防止SQL注入攻击
     * - 预编译语句，提高执行效率
     * - 结果集流式处理，支持大数据量
     * - 多结果集支持，处理复杂查询
     * - 执行计划缓存，优化重复查询
     * 
     * **安全机制**：
     * - SQL语法检查，防止恶意SQL
     * - 权限控制，基于用户角色的访问控制
     * - 查询超时，防止长时间阻塞
     * - 资源限制，防止资源耗尽
     * 
     * **使用场景**：
     * - 复杂的数据分析和统计查询
     * - 批量数据处理和迁移
     * - 数据库结构维护和优化
     * - 自定义的业务逻辑实现
     * 
     * **使用示例**：
     * @code
     * // 执行用户统计查询
     * UserStatResult statResult;
     * std::string sql = R"(
     *     SELECT 
     *         COUNT(*) as total_users,
     *         AVG(level) as avg_level,
     *         MAX(last_login) as last_active
     *     FROM user_info 
     *     WHERE create_time >= '2024-01-01'
     * )";
     * 
     * int ret = GetRpcExecuteService(NF_ST_GAME, 0, statResult, sql);
     * if (ret == 0) {
     *     NFLogInfo("查询成功 - 总用户数: {}, 平均等级: {}", 
     *               statResult.total_users(), statResult.avg_level());
     * }
     * @endcode
     * 
     * @warning 必须在协程上下文中调用
     * @warning 直接执行SQL可能存在安全风险，请谨慎使用
     * @warning 复杂SQL可能影响数据库性能，建议在低峰期执行
     * @note 支持事务处理，但需要手动管理事务状态
     * @note 大结果集会自动分批返回，避免内存溢出
     * @see GetRpcExecuteService 异步回调版本
     * @see GetRpcExecuteMoreService 多结果集版本
     */
    template <class DataType>
    int GetRpcExecuteService(NF_SERVER_TYPE eType, uint64_t mod_key, DataType& data, const std::string& sql, uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        std::string tempDBName = dbname;
        if (dbname.empty())
        {
            NFServerConfig* pConfig = FindModule<NFIConfigModule>()->GetAppConfig(eType);
            if (pConfig)
            {
                tempDBName = pConfig->DefaultDBName;
            }
        }
        CHECK_EXPR(!tempDBName.empty(), -1, "no dbname ........");

        if (dstBusId == 0)
        {
            auto pDbServer = FindModule<NFIMessageModule>()->GetSuitDbServer(eType, tempDBName, mod_key);
            if (pDbServer)
            {
                dstBusId = pDbServer->mServerInfo.bus_id();
            }
        }

        NFrame::storesvr_execute selobj;
        std::string clsname = NFProtobufCommon::GetProtoBaseName(data);
        //std::string packageName = NFProtobufCommon::GetProtoPackageName(data);
        CHECK_EXPR(!clsname.empty(), -1, "no clsname ........");
        NFStoreProtoCommon::storesvr_execute(selobj, tempDBName, clsname, mod_key, sql);
        NFrame::storesvr_execute_res selobjRes;
        int iRet = FindModule<NFIMessageModule>()->GetRpcService<NF_MODULE_FRAME, NFrame::NF_STORESVR_C2S_EXECUTE>(eType, NF_ST_STORE_SERVER, dstBusId, selobj, selobjRes);
        auto& opres = selobjRes.opres();
        if (iRet == 0 && opres.err_code() == 0)
        {
            data.ParsePartialFromString(selobjRes.record());
        }
        else
        {
            if (iRet == 0)
            {
                iRet = opres.err_code();
                NFLogError(NF_LOG_DEFAULT, 0, "NFrame::NF_STORESVR_C2S_EXECUTE Failed, iRet:{} errMsg:{}", GetErrorStr(iRet), opres.errmsg());
            }
            else
            {
                NFLogError(NF_LOG_DEFAULT, 0, "GetRpcService Failed, iRet:{}", GetErrorStr(iRet));
            }
        }
        return iRet;
    }

    /**
     * @brief 获取RPC执行服务（回调版本）
     *
     * 通过RPC调用向存储服务器执行SQL语句，支持回调函数
     *
     * @tparam ResponFunc 响应函数类型模板参数
     * @param eType 目标服务器类型
     * @param mod_key 模块键，用于哈希一致性
     * @param sql SQL语句
     * @param func 回调函数，用于处理操作结果
     * @param dstBusId 目标Bus ID，默认为0（自动选择）
     * @param dbname 数据库名，默认为空（使用默认数据库）
     * @return 协程ID
     */
    template <typename ResponFunc>
    int GetRpcExecuteService(NF_SERVER_TYPE eType, uint64_t mod_key, const std::string& sql, const ResponFunc& func, uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        return GetRpcExecuteServiceInner(eType, mod_key, sql, func, &ResponFunc::operator(), dstBusId, dbname);
    }

private:
    template <class DataType, typename ResponFunc>
    int64_t GetRpcExecuteServiceInner(NF_SERVER_TYPE eType, uint64_t mod_key, const std::string& sql, const ResponFunc& responFunc, void (ResponFunc::*pf)(int rpcRetCode, DataType& respone) const, uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        int64_t iRet = FindModule<NFICoroutineModule>()->MakeCoroutine([=]()
        {
            DataType respone;
            int rpcRetCode = GetRpcExecuteService(eType, mod_key, respone, sql, dstBusId, dbname);
            (responFunc.*pf)(rpcRetCode, respone);
        });
        return iRet;
    }

public:
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////store server select////////////////////////////////////////////////////////////////////////////
    /**
     * @brief 获取RPC执行多条记录服务（模板版本）
     *
     * 通过RPC调用向存储服务器执行SQL语句，返回多条记录
     *
     * @tparam DataType 数据类型模板参数
     * @param eType 目标服务器类型
     * @param mod_key 模块键，用于哈希一致性
     * @param respone 响应数据列表，用于存储执行结果
     * @param sql SQL语句
     * @param max_records 最大记录数，默认为100
     * @param dstBusId 目标Bus ID，默认为0（自动选择）
     * @param dbname 数据库名，默认为空（使用默认数据库）
     * @return 操作结果，0表示成功
     */
    template <typename DataType>
    int GetRpcExecuteMoreService(NF_SERVER_TYPE eType, uint64_t mod_key, std::vector<DataType>& respone, const std::string& sql, int max_records = 100, uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        std::string tempDBName = dbname;
        if (dbname.empty())
        {
            NFServerConfig* pConfig = FindModule<NFIConfigModule>()->GetAppConfig(eType);
            if (pConfig)
            {
                tempDBName = pConfig->DefaultDBName;
            }
        }
        CHECK_EXPR(!tempDBName.empty(), -1, "no dbname ........");

        if (dstBusId == 0)
        {
            auto pDbServer = FindModule<NFIMessageModule>()->GetSuitDbServer(eType, tempDBName, mod_key);
            if (pDbServer)
            {
                dstBusId = pDbServer->mServerInfo.bus_id();
            }
        }

        DataType data;
        NFrame::storesvr_execute_more sel;
        std::string tbname = NFProtobufCommon::GetProtoBaseName(data);
        std::string packageName = NFProtobufCommon::GetProtoPackageName(data);
        CHECK_EXPR(!tbname.empty(), -1, "no tbname ........");

        NFStoreProtoCommon::storesvr_execute_more(sel, tempDBName, tbname, mod_key, sql, max_records, tbname, packageName);
        NFrame::storesvr_execute_more_res selRes;
        STATIC_ASSERT_BIND_RPC_SERVICE(NFrame::NF_STORESVR_C2S_EXECUTE_MORE, NFrame::storesvr_execute_more, NFrame::storesvr_execute_more_res);
        NF_ASSERT_MSG(FindModule<NFICoroutineModule>()->IsInCoroutine(), "Call GetRpcService Must Int the Coroutine");
        NFServerConfig* pConfig = FindModule<NFIConfigModule>()->GetAppConfig(eType);
        CHECK_EXPR(pConfig, -1, "can't find server config! servertype:{}", GetServerName(eType));

        NFrame::Proto_FramePkg svrPkg;
        svrPkg.set_module_id(NF_MODULE_FRAME);
        svrPkg.set_msg_id(NFrame::NF_STORESVR_C2S_EXECUTE_MORE);
        svrPkg.set_msg_data(sel.SerializePartialAsString());
        auto pRpcInfo = svrPkg.mutable_rpc_info();
        pRpcInfo->set_req_rpc_id(FindModule<NFICoroutineModule>()->CurrentTaskId());
        pRpcInfo->set_req_rpc_hash(NFHash::hash<std::string>()(sel.GetTypeName()));
        pRpcInfo->set_rsp_rpc_hash(NFHash::hash<std::string>()(selRes.GetTypeName()));
        pRpcInfo->set_req_server_type(eType);
        pRpcInfo->set_req_bus_id(pConfig->BusId);

        FindModule<NFIMessageModule>()->SendMsgToServer(eType, NF_ST_STORE_SERVER, pConfig->BusId, dstBusId, NF_MODULE_FRAME, NFrame::NF_SERVER_TO_SERVER_RPC_CMD, svrPkg);

        int iRet = FindModule<NFICoroutineModule>()->SetUserData(&selRes);
        CHECK_EXPR(iRet == 0, iRet, "Yield Failed, Error:{}", GetErrorStr(iRet));

        do
        {
            iRet = FindModule<NFICoroutineModule>()->Yield(DEFINE_RPC_SERVICE_TIME_OUT_MS);
            CHECK_EXPR(iRet == 0, iRet, "Yield Failed, Error:{}", GetErrorStr(iRet));
            auto& opres = selRes.opres();
            if (iRet == 0 && opres.err_code() == 0)
            {
                for (int i = 0; i < selRes.record_size(); i++)
                {
                    DataType result;
                    result.ParsePartialFromString(selRes.record(i));
                    respone.push_back(result);
                }

                if (selRes.is_lastbatch())
                {
                    break;
                }
            }
            else
            {
                if (iRet == 0)
                {
                    iRet = opres.err_code();
                    NFLogError(NF_LOG_DEFAULT, 0, "NFrame::NF_STORESVR_C2S_EXECUTE_MORE Failed, iRet:{} errMsg:{}", GetErrorStr(iRet), opres.errmsg());
                }
                else
                {
                    NFLogError(NF_LOG_DEFAULT, 0, "GetRpcService Failed, iRet:{}", GetErrorStr(iRet));
                }

                break;
            }
        }
        while (true);

        FindModule<NFICoroutineModule>()->SetUserData(nullptr);

        return iRet;
    }

    /**
     * @brief 获取RPC执行多条记录服务（回调版本）
     *
     * 通过RPC调用向存储服务器执行SQL语句，返回多条记录，支持回调函数
     *
     * @tparam ResponFunc 响应函数类型模板参数
     * @param eType 目标服务器类型
     * @param mod_key 模块键，用于哈希一致性
     * @param sql SQL语句
     * @param func 回调函数，用于处理操作结果
     * @param max_records 最大记录数，默认为100
     * @param dstBusId 目标Bus ID，默认为0（自动选择）
     * @param dbname 数据库名，默认为空（使用默认数据库）
     * @return 协程ID
     */
    template <typename ResponFunc>
    int64_t GetRpcExecuteMoreService(NF_SERVER_TYPE eType, uint64_t mod_key, const std::string& sql, const ResponFunc& func, int max_records = 100, uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        return GetRpcExecuteMoreServiceInner(eType, mod_key, sql, func, &ResponFunc::operator(), max_records, dstBusId, dbname);
    }

private:
    template <class DataType, typename ResponFunc>
    int64_t GetRpcExecuteMoreServiceInner(NF_SERVER_TYPE eType, uint64_t mod_key, const std::string& sql, const ResponFunc& responFunc, void (ResponFunc::*pf)(int rpcRetCode, std::vector<DataType>& respone) const, int max_records = 100, uint32_t dstBusId = 0, const std::string& dbname = "")
    {
        int64_t iRet = FindModule<NFICoroutineModule>()->MakeCoroutine([=]()
        {
            std::vector<DataType> respone;
            int rpcRetCode = GetRpcExecuteMoreService(eType, mod_key, respone, sql, max_records, dstBusId, dbname);

            (responFunc.*pf)(rpcRetCode, respone);
        });
        return iRet;
    }
};
